Gui_ex.py broken. Any working examples?

Dear all,

I’m trying to build a GUI using PyROOT.
From Wim’s comments elsewhere, it seems that $ROOTSYS/tutorials/pyroot/gui_ex.py should show the recommended way. However, this example does not seem robust:

  1. when I run it as python gui_ex.py, it just segfaults
  2. when I run it from ipython, a window opens up.
    2.1 If I close it using the window manager, all appears well. But when I run it again, it segfaults.
    2.2 If I close it using the “Exit” button, it hangs for a while then segfaults

On the plus side, the “Draw” button seems to work well.

BTW: for those trying this at home, it tends to mess up the terminal. “stty sane” is your friend (yet another hint from Wim’s old posts).
Does anyone have a working example of opening a GUI window, displaying some ROOT object in it, and closing that window that properly handles all the objects and the lifetimes (e.g. can be re-entered)?

many thanks,
Amnon Harel

Hi,

I’m not a Python expert, but see [url=https://root-forum.cern.ch/t/handling-keys-in-application/19407/1 post[/url]

Cheers, Bertrand.

Hi Bertrand,

Your example works (with minor caveats listed below), but it doesn’t display any “normal” root object (function, histogram, etc.), which is key part of what I want to accomplish. I see that I failed to make this explicit in my original post. My apologies.

So I tried adding a R.TRootEmbeddedCanvas

This line by itself is enough to destabilize everything.
It does not matter whether or not I add the frame with

Once I use TRootEmbeddedCanvas:
A. when I run the script the second time, I get warnings as listed below.
B. when I try to exit the script the second time, ipython/ROOT hangs/segfaults.
C. when I try to quit ipython it hangs.

Any ideas how to properly manage the objects so I can embed a canvas and draw histograms on it?
I assume this is the problem, rather than TRootEmbeddedCanvas itself being buggy.

thanks,
Amnon

The minor caveats:

  1. It quits everything. So I commented out the last two lines of the quit method and it behaves smoothly. Can enter and exit it many times in a single ipython session.
  2. ipython does not like “from ROOT import *”, so I did the usual “import ROOT as R” and modified the code accordingly.

The warnings:

Error in <RootX11ErrorHandler>: BadDrawable (invalid Pixmap or Window parameter) (TGCompositeFrame XID: 65011912, XREQ: 62) TGCompositeFrame: 65011912 TGViewPort: 65011886 TRootEmbeddedCanvas: 65011885 TGMainFrame: 65011918 Error in <RootX11ErrorHandler>: BadWindow (invalid Window parameter) (TGCompositeFrame XID: 65011912, XREQ: 2) TGCompositeFrame: 65011912 TGViewPort: 65011886 TRootEmbeddedCanvas: 65011885 TGMainFrame: 65011918

Hi Amnon,

OK, so the code below works with ROOT v5-34-00-patches and Python 2.7 on Windows and Linux:

[code]from ROOT import *

class pMainFrame( TGMainFrame ):
def init( self, parent, width, height ):
TGMainFrame.init( self, parent, width, height )

  self.SetCleanup(kDeepCleanup)
  self.fCanvas = TRootEmbeddedCanvas( 'canvas', self, 40, 40 )
  self.AddFrame( self.fCanvas, TGLayoutHints( kLHintsExpandX | kLHintsExpandY, 20, 20, 20, 5) )

  self.fTextEntry = TGTextEntry( self, '' , 50)
  self.AddFrame( self.fTextEntry, TGLayoutHints( kLHintsExpandX | kLHintsTop, 20, 20, 5, 5) )

  self.fButton = TGTextButton( self, 'E&xit Application', 10 )
  self.AddFrame( self.fButton, TGLayoutHints( kLHintsExpandX | kLHintsTop, 20, 20, 5, 20) )
  self.fQuitDispatch = TPyDispatcher( self.quit )
  self.fButton.Connect( 'Clicked()', 'TPyDispatcher', self.fQuitDispatch, 'Dispatch()' )

  self.MapSubwindows()
  self.Layout()
  self.MapWindow()

  self.f2 = TF2( 'f2', 'x**2 + y**2 - x**3 -8*x*y**4', -1, 1.2, -1.5, 1.5 )
  self.f2.SetContour( 48 )
  self.f2.SetFillColor( 45 )

  canvas = self.fCanvas.GetCanvas()
  canvas.cd()
  canvas.SetPhi( -80 )
  canvas.SetLogz()
  self.f2.Draw( 'surf4' )

def del( self ):
self.Cleanup()

def quit(self):
print 'Bye bye…'
self.CloseWindow()
gApplication.Terminate()
exit()

if name == ‘main’:
window = pMainFrame( gClient.GetRoot(), 500, 500 )

[/code]
:exclamation: note the self.SetCleanup(kDeepCleanup)
If you still have a problem, please post a short script reproducing the issue, and tell us which version of ROOT, with which version of Python, and on which OS. Thanks.

Cheers, Bertrand.

Hi Bertrand,

Yep! self.SetCleanup( R.kDeepCleanup ) solves the memory management issues. :smiley:
This should probably be in the documentation somewhere. But at least now it’s in this archive and can be picked up by the search engines.

But how do I capture key presses inside the TRootEmbeddedCanvas?
They are not captured by the self–>m–>PrintMessage chain. :cry:

I also tried self.fCanvas.Connect( 'ProcessedEvent(Event_t*)', 'TPyDispatcher', m2, 'Dispatch(Event_t*)' ) with m2 defined similarly to m (*), but this did not capture the keys pressed in the canvas.

BTW: the only reason I got into this GUI stuff is that I wanted to capture keys pressed in the gPad and have my python code react to them. The relevant advice I found (documentation+archives) was to build a GUI and have it display a canvas. This made a lot of sense, and so here we are.

BTW2: I attached the file as you requested, but it’s basically the same as the code you pasted.

many thanks,
Amnon Harel

The definition of m2:

def PrintMessage2( event ):
   if event.fType == R.kGKeyPress:
      print "PrintMessage2() : key pressed!"

m2 = R.TPyDispatcher( PrintMessage2 )

pyroot_gui2.py (2.43 KB)

Hi Amnon,

[quote=“harelamnon”]But how do I capture key presses inside the TRootEmbeddedCanvas?
They are not captured by the self–>m–>PrintMessage chain.[/quote]
You have to connect to its container, which is processing (and forwarding) the events:

self.canvas.GetContainer().Connect( 'ProcessedEvent(Event_t*)', 'TPyDispatcher', m2, 'Dispatch(Event_t*)' )
Cheers, Bertrand.

Thanks Bertrand!

I think that covers everything I wanted to find in the examples and I can now build my simple GUI.
In the hope that this will be useful to others, I attach a small demo that includes text (TGLabel) and a TF1 that are updated in response to key presses, with everything is stable and re-entrant. Basically this the example I was hoping to find documented somewhere, showing the recommended way to have a canvas that responds to key presses. Since I’m a complete newbie in ROOT’s GUI, I’m sure the experts can improve upon the code in this demo.

cheers,
Amnon
pyroot_key_capturing_canvas.py (4 KB)