TCanvas popping up on construction

Is it possible to prevent TCanvas popping up and grabbing focus when it is constructed?

If I have a long running process or several canvases being created in succession, it makes my computer unusable whilst I am waiting for it to complete.

for (i = 0; i < 10; i++) { new TCanvas(); <wait a while> }

Hi Pete,

AFAIK, there is no such option, but if you need these canvases only for generating postscript, pdf, or pictures, you may want to use gROOT->SetBatch() to not popup these canvas at all…

Cheers,
Bertrand.

Hi,

If you are not running interactively (e.g., changing the canvases with your mouse), it is much faster to run in batch mode.

Cheers, Charles

Ah, but I do want to interact with these canvases. I only want to interact with them when they are all ready though. (I am familiar with batch mode and the speedup it brings).

Then the only option I see is to create them at the end of the time consuming process…

Can such a feature be added to delay the popping up of these canvases (or at least prevent their stealing focus from other programs) until TCanvas::Show is called?

The creation of the canvases itself is rather time consuming :confused:

Sure, we’ll see what can be done.

Cheers, Bertrand.

Thanks :slight_smile:

[quote=“pwaller”]Can such a feature be added to delay the popping up of these canvases
(or at least prevent their stealing focus from other programs) until TCanvas::Show is called?[/quote]

The “stealing focus” is a property (I believe) of your window manager and won’t under the control of Root.

Really? I would be somewhat surprised if it is not possible to create a window in the background, though I must admit I can’t recall having seen this on linux.

Whilst on the topic of TCanvas and batch,

If I do something like the following:

[code]TCanvas *myVisibleCanvas = new TCanvas();
gROOT.SetBatch();
TCanvas *myInvisibleCanvas = new TCanvas();
gROOT.SetBatch(false);

myVisibleCanvas->cd()

delete myInvisibleCanvas; // [1]
delete myVisibleCanvas;[/code]

I get a segfault at [1] because myInvisibleCanvas tries to delete a non-existent window instance. If I SetBatch() before deleting myInvisibleCanvas, all is well, but I would have hoped I wouldn’t have to do this. It is yet another thing to keep track of. It would be better if TCanvas worked out for itself whether it ever created a window it needs to delete.

Hi Pete,

This is the case, but there was a bug (for this particular case of batch and non-batch mix) which is now fixed in svn trunk. Thanks for the example and sorry for the trouble.

Cheers, Bertrand.

Sorry for digging this thread, but…

Indeed, and it seems that Gnome stealing focus management is quite poor.

However, in some case there is a workaround : updating an existing TCanvas. This is what I would like to achieve in a particular case : I have a TFile in which are stored TCanvas, which I can draw in an interactive session using myfile->Get(“canvasname”)->Draw() (or, probably better, ((TCanvas*)(myfile->Get(“canvasname”)))->Draw()). But I have many canvas to check, so the focus stealing is very, very annoying.

Is there a way I could make each canvas to update the previous one, instead of replacing it ?

Hi,
One option could be to not call Draw() on the canvas, but to take the list of primitives from the canvas and draw them in your own canvas. Something like this:

TObject *obj, *clone; TCanvas *mycanvas = new TCanvas("mycanvas", "My Canvas"); TCanvas *canvas = (TCanvas*)myfile->Get("canvasname"); if (canvas == 0) return; TIter next(canvas->GetListOfPrimitives()); while ((obj=next())) { mycanvas->cd(); clone = obj->Clone(); mycanvas->GetListOfPrimitives()->Add(clone,next.GetOption()); } Note: I didn’t try, so maybe there will be something missing…

Cheers, Bertrand.

Indeed the redrawing is missing (maybe it was intended), but apart from that it works fine, thanks !

I created moved the following to a macro :

void plotcanvas() { TObject *obj, *clone; if (canvas == 0) return; TIter next(canvas->GetListOfPrimitives()); while ((obj=next())) { mycanvas->cd(); clone = obj->Clone(); mycanvas->GetListOfPrimitives()->Add(clone,next.GetOption()); } mycanvas->Draw(); return; }
then loaded it in the interactive session, and I just have to type the following lines :

TCanvas *canvas = ((TCanvas*)(myfile->Get("canvasname"))) plotcanvas()

Many thanks !