Updating canvas using TApplication

I would like to display graphics in a compiled program (using TApplication) where I can update the canvas with a press of a key. I tried this simple code (see below), but the line c1->Update() does not seem to display the new graphics nor does using the Draw() method. How can I refresh the canvas graphics?

#include <iostream>
#include "TMarker.h"
#include "TApplication.h"
#include "TCanvas.h"

using namespace std;

int main(int argc, char *argv[])
{
  TApplication *app = new TApplication("app", 0, 0);

  TCanvas *c1 = new TCanvas("c1", "test", 200, 200);

  TMarker *mark = new TMarker(0.5, 0.5, 22);
  mark->SetMarkerSize(10);

  mark->Draw();
  c1->Update();
  cin.ignore();

  mark->SetMarkerColor(2);
  mark->Draw();
  c1->Update();

  app->Run();

  return 0;
}

there is some example on the forum. May be see:

For me, the best foolproof method is (instead of “gPad”, you may use the pointer to your canvas “c1”):

#include "TPad.h" #include "TSystem.h" // ... gPad->Modified(); gPad->Update(); gSystem->ProcessEvents(); BTW. I think a better method to create the TApplication would be: int itmp = (argc > 1 ? 1 : argc); TApplication *app = new TApplication("app", &itmp, argv);

It seems that I was missing the line ‘gSystem->ProcessEvents();’, but when I modified my code to include this, I get the same results as before, namely I do not see the original black marker drawn on the canvas and the canvas is inactive. Here is the code:

#include
#include “TMarker.h”
#include “TApplication.h”
#include “TCanvas.h”
#include “TSystem.h”

using namespace std;

int main(int argc, char *argv[])
{
TApplication *app = new TApplication(“app”, &argc, argv);

TCanvas *c1 = new TCanvas(“c1”, “test”, 200, 200);

TMarker *mark = new TMarker(0.5, 0.5, 22);
mark->SetMarkerSize(10);

mark->Draw();
c1->Modified();
c1->Update();
gSystem->ProcessEvents();
cin.ignore();

mark->SetMarkerColor(2);
mark->Draw();
c1->Modified();
c1->Update();
gSystem->ProcessEvents();

app->Run();

return 0;
}

What exactly is gSystem->ProcessEvents() doing?

I tried ROOT 5.28 and 5.34 on Linux (did you remember to recompile your executable after changes?).
In both cases I can see the black triangle first, and then, after I press “enter”, I can see the red triangle.
Note … you cannot do anything interactively in the “c1” canvas until it enters “app->Run();” (so, until after there’s the red triangle visible).
See also: http://root.cern.ch/root/html/TSystem.html#TSystem:ProcessEvents

I did recompile the code after changes. I ran the program on a Mac running OS 10.7 and ROOT 5.30 and also on a Linux laptop running ROOT 5.24. Both times I get the same results. I do not see the black triangle and only the red one. You can see the output in the pictures below.




I also compiled using “g++ root-config --libs --cflags -o test_draw test_draw.cpp” to get the executable. Is this the same as what you did Pepe?

The first picture that you posted looks like the “gSystem->ProcessEvents();” was not executed at all -> this picture should look exactly like the second picture, except that the triangle should be black.
I use: `root-config --cxx --cflags` -o app app.cxx `root-config --glibs` You could try: g++ `root-config --cflags` -o app app.cxx `root-config --glibs`
I have no practice with MacOS, sorry.
(I have just tried it on another Linux with a very ancient ROOT 5.18 and it works well, too.)

Well, it seems I also get this problem …
I’ve been trying to execute the “app” multiple times … and sometimes it works well, but sometimes it fails.
Right after the canvas is drawn, I press “Ctrl-C”, to kill the “app” … and then I run it again … and then it often fails … there is no black triangle (and sometimes the black triangle is there but the menu is not there).
That is with Ubuntu 10.04.4 LTS / i686 and ROOT 5.34 and 5.28.

Maybe you could try to add: gSystem->Sleep(100); right before “gSystem->ProcessEvents();” … this seems to help in my case (no idea why).

Hi,

cin.ignore();blocks the (only) threads and no event can be process. If you want to be able to interact with the canvas while waiting for user input, the easiest is to use WaitPrimitive (see for example TPad::WaitPrimitive()).

Cheers,
Philippe.

Well, even if it’s “blocked” … should I expect the screen contents to be fully updated after “ProcessEvents” (right before “cin.ignore();”) or should I not?
And if not, can one call any method that will make sure that everything’s updated on the screen (instead of “ProcessEvents”)?

If I replace gSystem->ProcessEvents() with c1->WaitPrimitive(), it seems to work, but I have to either press enter with the canvas as the active window, or double click in the canvas when it is active. Is the c1->Modified() necessary? What does this do?

I do not understand what is meant by the thread being blocked so no event can be processed due to cin.ignore(). What is the meaning of event here, the Draw() from TMarker or something else?

In the majority of cases, you do not need to call “Modified” before “Update”. However, I have had cases when this additional call was necessary (otherwise the display was not properly updated), so I usually add this call just as a “precaution”, even though I know it’s usually “superfluous”.