mixing OpenGL and Qt drawing

947 views
Skip to first unread message

wab...@gmail.com

unread,
Jun 23, 2014, 12:40:48 PM6/23/14
to pyqt...@googlegroups.com
We want to have OpenGL and Qt drawing on the same widget.  We are using OpenGL for stuff that would be too slow in Qt, and Qt for everything else.  As far as I understand, the way to do this in Qt itself is to create a QGraphicsScene, and then you can create Qt and OpenGL QGraphicsItems and mix them as need be.  This seems to work ok.  It would be nice to be able to put such a scene into a pyqtgraph PlotWidget (so I can get to use AxisItem, etc.), but this doesn't look possible.  Am I missing something?

Luke Campagnola

unread,
Jun 23, 2014, 1:32:02 PM6/23/14
to pyqt...@googlegroups.com
On Mon, Jun 23, 2014 at 12:40 PM, <wab...@gmail.com> wrote:
We want to have OpenGL and Qt drawing on the same widget.  We are using OpenGL for stuff that would be too slow in Qt, and Qt for everything else.  As far as I understand, the way to do this in Qt itself is to create a QGraphicsScene, and then you can create Qt and OpenGL QGraphicsItems and mix them as need be.  This seems to work ok.  It would be nice to be able to put such a scene into a pyqtgraph PlotWidget (so I can get to use AxisItem, etc.), but this doesn't look possible.  Am I missing something?

This should work even inside a PlotWidget--this is exactly the method we hope to use to integrate vispy's visuals with the Qt scenegraph. Please post an example if you are unable to make it work.

The important pieces are 1) your GraphicsView instances must be configured to use OpenGL (see http://www.pyqtgraph.org/documentation/widgets/graphicsview.html#pyqtgraph.GraphicsView), and 2) you must write subclasses of QGraphicsItem that include the relevant OpenGL calls inside their paint() methods. (see http://qt-project.org/doc/qt-4.8/qpainter.html#beginNativePainting).


wab...@gmail.com

unread,
Jun 24, 2014, 12:11:10 PM6/24/14
to pyqt...@googlegroups.com
Thanks for the reply, I have finally managed to get something to partly work.  I was originally trying to subclass a QGraphicsScene, but it looks like this is not what you are supposed to do.  Instead you are supposed to use the PlotWidget's scene, is that correct?

It looks like that scene draws over the entire plot, so including on top of the axes, rather than inside the ViewBox.  And it looks like it ignores the zooming / panning of the plot.  I guess both of these make sense.

It also looks like the useOpenGL flag is irrelevant for this purpose, and the documentation implies (if I am understanding it correctly) that this flag is in case you want the Qt drawing to use OpenGL, rather than if you happen to want to draw in OpenGL.

One niggle is that if you click with the mouse the OpenGL disappears, but presumably that is because the code is missing some function call.

It also looks like the ViewBox drawing is done before the rest of the scene drawing.  (We want the OpenGL to be the bottom layer, so to speak.)

I've attached a file in case this is completely wrong approach (the code is not minimal but near enough).


TestPyQtGl.py

Luke Campagnola

unread,
Jun 24, 2014, 12:44:50 PM6/24/14
to pyqt...@googlegroups.com
On Tue, Jun 24, 2014 at 12:11 PM, <wab...@gmail.com> wrote:
Thanks for the reply, I have finally managed to get something to partly work.  I was originally trying to subclass a QGraphicsScene, but it looks like this is not what you are supposed to do.  Instead you are supposed to use the PlotWidget's scene, is that correct?

Correct. At the top level, you always have one QGraphicsView widget (of which PlotWidget is a subclasss) and one QGraphicsScene, which contains all of the items to be drawn inside of the view. PlotWidget provides its own GraphicsScene already, so I don't think there is a reason to provide your own.
 
It looks like that scene draws over the entire plot, so including on top of the axes, rather than inside the ViewBox.  And it looks like it ignores the zooming / panning of the plot.  I guess both of these make sense.

Correct; the PlotItem, AxisItems, ViewBox, and data are all just items that live somewhere inside the scene. Only the items that live within the ViewBox are actually affected by its zoom/pan transformation.
 
It also looks like the useOpenGL flag is irrelevant for this purpose, and the documentation implies (if I am understanding it correctly) that this flag is in case you want the Qt drawing to use OpenGL, rather than if you happen to want to draw in OpenGL.

The useOpenGL flag causes the underlying drawing surface to be switched from QWidget to QGLWidget (internally this calls QGraphicsView.setViewport), which I believe is required to be able to do any opengl drawing. It looks like you are manually calling setViewport, though, which would explain why useOpenGL has no effect for you.
 
One niggle is that if you click with the mouse the OpenGL disappears, but presumably that is because the code is missing some function call.

This is because you have not stored the item anywhere and it is being collected by python after the first draw.
 
It also looks like the ViewBox drawing is done before the rest of the scene drawing.  (We want the OpenGL to be the bottom layer, so to speak.)

Use QGraphicsItem.setZValue() to change the order in which items are drawn.

Thanks for providing the example script!
I should also point you to some experimental code in PlotCurveItem.paintGL -- this is an early attempt to use opengl for faster plot rendering (it is called from PlotCurveItem.paint only if the 'enableExperimental' globnal config option is set). It includes stenciling to allow the line to be clipped by the ViewBox. The plan is to eventually replace that with calls to vispy, which will provide nice antialiased lines, fills, etc.

wab...@gmail.com

unread,
Jun 25, 2014, 9:11:11 AM6/25/14
to pyqt...@googlegroups.com
Thanks, that is all good to know.

The code crashes (as in a fatal OpenGL-like crash, not a calm Python crash) without the line:

    self.setViewport(QtOpenGL.QGLWidget())

I'm using Anaconda with Python 3.3 and with PySide (I forget which version of that) and possibly it would not crash with other implementations.  But anyway easy enough to have that line.
Reply all
Reply to author
Forward
0 new messages