Crash using TRootEmbeddedCanvas

Hello everyone,

I’m seeing a crash with python 2.5.2 with ROOT 5.20/00, when trying to create a gui containing a TRootEmbeddedCanvas.

In short : creating 2 instances of a gui containing a TRootEmbeddedCanvas causes a crash.

gui_pyroot> python -i debug.py
>>> b.build()
LArGui : thread =  -1208944448 self=  <ROOT.TGMainFrame object ("fMainFrame2") at 0x8b8d0c8>
emb canvas =  <ROOT.TRootEmbeddedCanvas object ("fRootEmbeddedCanvas4") at 0x8bbee08>
>>> b.build()
LArGui : thread =  -1208944448 self=  <ROOT.TGMainFrame object ("fMainFrame16") at 0x8c28560>
emb canvas =  <ROOT.TRootEmbeddedCanvas object ("fRootEmbeddedCanvas18") at 0x8c28710>
>>> Error in <RootX11ErrorHandler>: BadDrawable (invalid Pixmap or Window parameter) (TGCompositeFrame XID: 37748995, XREQ: 62)
TGCompositeFrame:	37748995
	TGViewPort:	37748969
	TRootEmbeddedCanvas:	37748968
	TGVerticalFrame:	37748967
	TGVerticalFrame:	37749002
	TGMainFrame:	37749001

After that the program hangs and I have to kill it manually.

The code in debug.py is simply :

import ROOT
import thread

class builder:
    def __init__(self):
        self.gui = None
    def build(self):
        self.gui = MyGui(ROOT.gClient.GetRoot())
        self.gui.init_gui()


b = builder()


class MyGui(ROOT.TGMainFrame):
    def __init__(self, p):
        ROOT.TGMainFrame.__init__(self,p,600,400)
        print 'LArGui : thread = ', thread.get_ident(), 'self= ',self


    def init_gui(self):

        self.ChangeOptions( self.GetOptions() | ROOT.kVerticalFrame)        

        # main vertical frame
        self.mvert = ROOT.TGVerticalFrame(self,300,300, ROOT.kFitWidth| ROOT.kFitHeight)

        self.canvas = ROOT.TRootEmbeddedCanvas("Ecanvas",self.mvert,200,200)
        print 'emb canvas = ', self.canvas
        self.mvert.AddFrame( self.canvas,ROOT.TGLayoutHints(ROOT.kLHintsTop | ROOT.kLHintsExpandX| ROOT.kLHintsExpandY))


        self.AddFrame(self.mvert, ROOT.TGLayoutHints(ROOT.kLHintsTop | ROOT.kLHintsExpandX | ROOT.kLHintsExpandY))

        self.MapSubwindows()        
        self.Layout()
        self.SetWindowName("Tool")
        self.SetIconName("Tool")  
        self.MapWindow()

Actually I don’t see a crash if I keep the different python instance of the gui alive in a list. But I’d like to advoid that, if possible…

Do you want to keep the original window alive and create a second one, or do you want to cleanly destroy the old one and subsequently create another one?

If it is all just a matter of “not crashing” then you’ll need to manually remove the old canvas from the gROOT list of canvases (dunno why; might just be timing). Something like this: def build(self): if ( self.gui ): ROOT.gROOT.GetListOfCanvases().Remove( self.gui.canvas.GetCanvas() ) self.gui = None self.gui = MyGui(ROOT.gClient.GetRoot()) self.gui.init_gui() appears to do the trick for me.

Cheers,
Wim

Wim,

I want to cleanly destroy old instances. So I’ll use your trick when needed.

thanks a lot for your help.