I have written a small Root macro with a GUI and I have some troubles trying to exit from it.
The main requirement is that exiting must not close the Root session, since other processes depend on it. Therefore, I could not simply connect the exit button to some
"gApplication->Terminate(0);".
Instead, I have tried to use something like
where fMain is my TGMainFrame.
This seems to close the window correcly, but immediately after that the Root session (and in fact the whole terminal) crashes with a segfault, telling me
Well, fMain->CloseWindow(); is not sufficient, you have to delete (cleanup) your GUI elements, e.g. in this case the TRootEmbeddedCanvas. You can aslo try to use fMain->SetCleanup(kDeepCleanup).
If you still have problems, please post your code, or at least a snapshot reproducing the problem.
sorry, I should maybe have posted a bit more of my code. Of course I do a
fMain->Cleanup();
as well, but it does not seem to help. Also a
fMain->SetCleanup(kDeepCleanup);
does not seem to make any difference.
A very simple example to reproduce the problem is in fact the first example described in the Root Users Guide. I have attached it for easy access. As long as you use the Exit button in this case, everything works fine but the Root session is also quit. However, when you close the window directly, this gives the segfault I have described above. Hence, I could rephrase my question: How would a slot method look like to which I can connect the Exit button and which exits the macro but leaves the Root session alive?
Here is an example:[code]MyMainFrame::MyMainFrame(const TGWindow *p,UInt_t w,UInt_t h) {
// Create a main frame
fMain = new TGMainFrame(p,w,h);
fMain->SetCleanup(kDeepCleanup);
fMain->Connect(“CloseWindow()”, “MyMainFrame”, this, “DoClose()”);
fMain->DontCallClose(); // to avoid double deletions.
[…]
TGTextButton *exit = new TGTextButton(hframe,"&Exit");
exit->Connect(“Clicked()”,“MyMainFrame”,this,“DoClose()”);
[…]
MyMainFrame::~MyMainFrame() {
// Clean up used widgets: frames, buttons, layouthints
fMain->CloseWindow();
}
void MyMainFrame::DoClose() {
// Close window slot: delete this and really close the window
delete this;
}[/code]
Just try the (modified) script in attachment (it works fine for me on Linux and Windows).
I’m reviving this thread because I hit a very similar pbm.
I couldn’t adapt the solution proposed above in the case where one use
a TRootEmbeddedCanvas in a class directly inheriting TGMainFrame (rather than in a class embedding a TGMainFrame).
I’m using the attached small script in an interactive session. I do :
g = new TestGui(gClient->GetRoot())
g->init()
then close the gui window which provokes the crash.
I have a similar crash when closing the window when running the tutorial/gui/statusBar.C script.
There’s probably an obvious solution I’ve missed ?
int wembCanvas = embCanvas->GetCanvasWindowId();
TCanvas *c123 = new TCanvas("c123", 10, 10, wembCanvas);
embCanvas->AdoptCanvas(c123);
To get the pointer of the TCanvas created in the TRootEmbeddedCanvas, doing this is sufficient:
TCanvas *c123 = embCanvas->GetCanvas();
And if you really need to create you own canvas, just delete the original one like this:
delete embCanvas->GetCanvas();
int wembCanvas = embCanvas->GetCanvasWindowId();
TCanvas *c123 = new TCanvas("c123", 10, 10, wembCanvas);
embCanvas->AdoptCanvas(c123);
Usually, this kind of method: embCanvas->AdoptCanvas(c123); is useful if you have multiple canvases and want to exchange/replace canvases inside a TRootEmbeddedCanvas. But one has to take care of the creation/deletion of these canvases…