Displaying multiple TCanvas with a C++ application

Hello,

I’m new to the forum and not sure whether this is the right section for my question. If not, then I’m sorry, please feel free to send me to the right place. :slight_smile:

My problem is the following:
I am writing a C++ program that reads data files and uses them to create histograms and draws those into
TCanvas objects. The latter can be viewed by the user.

Now my first problem was that the TCanvas always disappeared upon briefly flashing up on the screen. I solved this by creating a TApplication object and calling the WaitPrimitive()-function for a Canvas that I wanted to display, so it looks like this:

TCanvas *display = giveMeMyCanvas();
display->Draw();
display->WaitPrimitive();

where giveMeMyCanvas() is a function that returns a pointer to a TCanvas object.

The problem with this solution, however, is that I can’t display more than one Canvas at a time in this way, because the program will stop until the Canvas is closed (or the user double-clicks on the Canvas*).

So my question would be this:
Is there another way to keep those Canvases displayed without interrupting the entire program like WaitPrimitive() does?

Thanks for any input on this,
Florian


*in principle I guess I could use the fact that the Canvas still remains displayed upon double-clicking it, but it becomes non-interactive by doing that, so I can no longer zoom into the histogram or use any other of the interactive features, which makes this less than ideal in my opinion.

1 Like

Try to draw the “canvas” using (all drawn canvases should have different “names”, of course): canvas->Draw(); canvas->Update(); then, when you draw “something” into this “canvas” use: something->Draw("some draw options"); canvas->Modified(); canvas->Update(); or: something->Draw("some draw options"); gPad->Modified(); gPad->Update(); finally, from time to time in your code (frequently enough that you don’t feel that your canvases became “non-interactive”), call: gSystem->ProcessEvents();

Well, unless what you wanted is just: #include "TApplication.h" int main(int argc, char **argv) { TApplication a("a", 0, 0); // ... // read all data files, create all histograms, draw all canvases // ... a.Run(kTRUE); // return here using "any canvas main menu" -> "File" -> "Quit ROOT" return 0; }

Thanks for the suggestions.

I tried

[quote=“Wile E. Coyote”]Try to draw the “canvas” using (all drawn canvases should have different “names”, of course): canvas->Draw(); canvas->Update(); then, when you draw “something” into this “canvas” use: something->Draw("some draw options"); canvas->Modified(); canvas->Update(); or: something->Draw("some draw options"); gPad->Modified(); gPad->Update();
[/quote]

which works fine in so far as it keeps my Canvas objects displayed. However, each Canvas seems to be non-interactive, i.e. I can use none of the features such as saving the Canvas to a file, zooming etc.
I called

right after drawing, but it changed nothing, unfortunately.

You have to call “gSystem->ProcessEvents();” IN REGULAR INTERVALS (i.e. many times).
For example, if you have any loop in your code, make this call once per iteration (or once per 10 or 100 iterations, if the execution of your loop is “fast”).

Yes, I got that. I created a test loop that basically looks like this:

for(int i = 1; i<10; i++){

  //create and draw canvases 

  gSystem->ProcessEvents();

  //wait for user input before entering next iteration step
}

The Canvas is still non-interactive.

Sorry, that’s not how it is supposed to work.
The “gSystem->ProcessEvents();” call will NOT wait for the user to do anything. If there are any “pending” events they will be “processed”, and if not, your program will simply “continue”.

Try:
grep -r ProcessEvents ${ROOTSYS}/tutorials
grep -r ProcessEvents ${ROOTSYS}/test
and see how it’s used there.

Thank you, I will look into those examples and see if I can get it to work.