Using Canvas in PyQt5 Application

Hi,

I have s question using a root canvas in a PyQt5 application. I have attached some source code to this message. When executed I get two different windows. One is the Qt5 Widget with a push button “Draw Histogram” and a black area where the root canvas should be displayed. However, the canvas is shown in a different window. Clicking on the push button generates a nice histogram in the canvas.
I think the error is connected to lines 24, 25 which are taken from a C++ example I found online. In case I use this code instead of line 26, I get the following error:

/usr/local/lib/ROOT.py:457: RuntimeWarning: creating converter for unknown type “TTVirtualX**”
attr = _root.LookupCppEntity( name, PyConfig.ExposeCppMacros )
Traceback (most recent call last):
File “./Canvas.py”, line 119, in
ex = QMainCanvas()
File “./Canvas.py”, line 72, in init
self.initUI()
File “./Canvas.py”, line 75, in initUI
self.canvas = Canvas(self)
File “./Canvas.py”, line 15, in init
self.initUI()
File “./Canvas.py”, line 24, in initUI
wid = gVirtualX.AddWindow(self.winId(), 600, 400)
AttributeError: ‘ROOT.PyLongBuffer’ object has no attribute ‘AddWindow’

Can someone help me out with a hint what I could change in my code to make it work properly?

Canvas.py (4.3 KB)

To mix windows, the parents should be properly set and the event handlers should direct to both. Maybe the $ROOTSYS/tutorials/pyroot/qtexample.py still works.

Hi,

Thanks for your answer, but I think this tutorial requires Qt4. I have to make it work with Qt5. I now compiled the C++ version of the above script and this seems to work quite fine (see attachment). So I think the uncommented lines in the script are important to “tell” the root canvas its window id in the operating system?

simple_canvas.tar.gz (2.4 KB)

And simply renaming PyQt4 -> PyQt5 does not work?

I don’t think you can do all the necessary interleaving work on the API side only. The window ids maybe, but the event loops most likely not. Anyway, the point was that that was all done in some ROOT internal classes which the mentioned example uses and likely you should, too. This was done in some gray past (the developer has since left), but it’s still featured in the user’s manual, so I’d figure it may all still work:

https://root.cern.ch/root/htmldoc/guides/users-guide/ROOTUsersGuide.html#rootqt-integration-interfaces

The documentation talks about “qtcint” rather than “qtcling”, so it’s quite possible that all this is rather obsolete, but then you’d still have the sources to see how to connect ids and event loops. (In some truly gray past ('96 or so), I once connected ROOT’s TCanvas with Microsoft MFC. It really was no more work than those two things: pass on the ids and setup a single event loop that feeds both frameworks. So if you can take those from QtRoot, you’re likely good to go, even if the rest of it no longer works.)

No It does not work.

File "qtexample.py", line 56, in <module>
    terminator = ROOT.TQtRootSlot.CintSlot()
  File "/usr/local/lib/ROOT.py", line 425, in __getattr1
    return getattr( self, name )
  File "/usr/local/lib/ROOT.py", line 468, in __getattr2
    raise AttributeError( name )
AttributeError: TQtRootSlot```

I think the issue already starts at the compilation of root. When I try to switch on qt support with -Dqt=on, cmake rightfully complains that it can only find qt5, not qt4. I actually did not want to mix qt4 and qt5. Well I will try to find a different solution. Thanks for your help!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.