Flicker (actually, image inversion) in existing QGraphicScene

304 views
Skip to first unread message

syr123

unread,
May 2, 2013, 1:57:31 PM5/2/13
to pyqt...@googlegroups.com
This is a strange one, so let me know if I'm making sense here.

I'm using PySide on OSX 10.7 with Python 2.7.  I have an application I've been writing for some time which has a UI consiting of a QGraphicsScene which frequently repopulated itself with items, as well as many QWidgets I've written with custom drawing code (nothing too fancy, just a lot of pixmap drawing, text, and rectangles).

I was psyched to find pyqtgraph, and did

import pyqtgraph

after my PySide imports to try to force it using PySide.  I've been able to plot and all is well.

However, I've noticed a few strange things since adding pyqtgraph to my project:

1)  The splash screen I wrote to come up when my app launched has started showing up as a blank image.  It was a transparent png.  If I comment out the pyqtgraph imports, it displays as usual.

2) And the most alarming:  with pyqtgraph imported in my project, at seemingly spurious moments while I'm using the application, (while my non pyqtgraph QGraphicsScene is repopulating,  or when I click the window containing my custom widgets [paint events]).  The entire window will 'flash' or 'flicker'.  Now, this is actually somewhat of a misnomer - what actually appears to be happening is that the entire buffer is inverting and drawing flipped across the horizontal center axis -- the window will draw upside down for one frame.  I've seen this happen before in my app when I've screwed something up in a custom paint routine, like forgetting to call QPainter.end().

Any ideas?  Some things I can think of:

   Do I need to be calling QApplication.setGraphicsSystem to something? Could that be an issue?

   Is this actually not a bug with pyqtgraph, but rather something about including pyqtgraph has caused a piece of my drawing code that was incorrect but was previously rendering alright to fail?

My only current solution is to totally decouple my pyqtgraph plotting from the rest of my application, and communicate data over a socket, which is a huge bummer.  So, any help would be most appreciated.

syr123

unread,
May 2, 2013, 2:05:04 PM5/2/13
to pyqt...@googlegroups.com
I should also point out I do not need OpenGL support - I'm only plotting in 2d and do not plan to utilize GL at all.

Luke Campagnola

unread,
May 2, 2013, 3:03:39 PM5/2/13
to pyqt...@googlegroups.com
On Thu, May 2, 2013 at 1:57 PM, syr123 <michael.fr...@gmail.com> wrote:
I'm using PySide on OSX 10.7 with Python 2.7.  I have an application I've been writing for some time which has a UI consiting of a QGraphicsScene which frequently repopulated itself with items, as well as many QWidgets I've written with custom drawing code (nothing too fancy, just a lot of pixmap drawing, text, and rectangles).

[snip]
However, I've noticed a few strange things since adding pyqtgraph to my project:

1)  The splash screen I wrote to come up when my app launched has started showing up as a blank image.  It was a transparent png.  If I comment out the pyqtgraph imports, it displays as usual.

2) And the most alarming:  with pyqtgraph imported in my project, at seemingly spurious moments while I'm using the application, (while my non pyqtgraph QGraphicsScene is repopulating,  or when I click the window containing my custom widgets [paint events]).  The entire window will 'flash' or 'flicker'.  Now, this is actually somewhat of a misnomer - what actually appears to be happening is that the entire buffer is inverting and drawing flipped across the horizontal center axis -- the window will draw upside down for one frame.  I've seen this happen before in my app when I've screwed something up in a custom paint routine, like forgetting to call QPainter.end().


This is very strange indeed! I presume you have already looked through this thread: https://groups.google.com/forum/#!searchin/pyqtgraph/flicker/pyqtgraph/wNywaYyQt7Y/lNf2fC3lNlQJ
The splash screen problem you described is somewhat reminiscent of the flickering we have seen with OSX previously. The vertical inversion, however, is completely new to me.  

For the record, could you send me the output of pg.systemInfo() on your machine?
 
Any ideas?  Some things I can think of:

   Do I need to be calling QApplication.setGraphicsSystem to something? Could that be an issue?

This is a good place to start, especially if just importing pyqtgraph causes problems for you--it actually makes a call to setGraphicsSystem when it is first started. The exact graphics system it will request depends on the version of pyqtgraph you have , though (I think the latest version asks for 'raster'). I would definitely recommend trying all of the different options here. Remember to call setGraphicsSystem after importing pyqtgraph and before creating the QApplication; otherwise it may have no effect. 

Question: Do you have the splash screen problem if you just import pyqtgraph but make no other calls to it (importantly, no QGraphicsView widgets are created by pyqtgraph) ?
 
   Is this actually not a bug with pyqtgraph, but rather something about including pyqtgraph has caused a piece of my drawing code that was incorrect but was previously rendering alright to fail?

I suspect the real bug is in the combination of QGraphicsView and OSX since we've seen so many problems there before. However, I consider it one of the goals of pyqtgraph to cover up as many upstream bugs as possible since many users of pyqtgraph have very specific version/platform requirements. With that in mind, it would be helpful if you could send a working example of the bugs you are seeing so we can either fix the bug in pyqtgraph or find an acceptable workaround (but please note that I am personally quite busy for the next 2-3 months, and might not be able to get to it immediately).
 
My only current solution is to totally decouple my pyqtgraph plotting from the rest of my application, and communicate data over a socket, which is a huge bummer.  So, any help would be most appreciated.

I agree that's the least desirable solution. However: pyqtgraph includes some code for controlling remote processes that might make this a lot easier for you (see pyqtgraph.multiprocess and pyqtgraph.widgets.RemoteGraphicsView), so long as we can at least make the library import without trouble in the main process.

I should also point out I do not need OpenGL support - I'm only plotting in 2d and do not plan to utilize GL at all.

This is another good thing to play with--try enabling/disabling opengl with pg.setConfigOptions(useOpenGL=True/False). I think this is also discussed in the thread I linked to above.


Luke 

syr123

unread,
Jun 2, 2013, 5:47:05 PM6/2/13
to pyqt...@googlegroups.com
Thanks for you fast and thorough response, Luke.  And if I didn't make it clear in my first post, a big thank you for maintaining and supporting this fantastic library.  I'm getting some great use out of it.

For the record, here's my system info:
>>> pyqtgraph.systemInfo()
sys.platform: darwin
sys.version: 2.7.3 (v2.7.3:70274d53c1dd, Apr  9 2012, 20:52:43) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)]
qt bindings: PySide 1.1.0
pyqtgraph: 0.9.7; None
config:
{'antialias': False,
 'background': (0, 0, 0),
 'editorCommand': None,
 'foreground': (150, 150, 150),
 'leftButtonPan': True,
 'useOpenGL': False,
 'useWeave': True,
 'weaveDebug': False}

I had read that other thread, tried setGraphicsSystem options and different import orders.  In the immediate, since it's not critical I have plotting in anything other than the debug mode of my application, I have two launchers, one with plotting and one without to avoid flicker...


On Thursday, May 2, 2013 10:57:31 AM UTC-7, syr123 wrote:

fox

unread,
Oct 2, 2013, 6:19:27 PM10/2/13
to pyqt...@googlegroups.com
I'm experiencing the same problem. Below is some code which recreates the problem. The first time I run it (i.e. when the QApplication is actually instanciated) then the panning/zooming works just fine (attached "Regular View.png") but the second time (i.e. when the QApplication.instance() is used) then when panning/zooming causes the buffer to flicker between regular and inverted (attached "Inverted View.png").



import numpy as np
import pyqtgraph as pg
from pyqtgraph import QtGui, QtCore

def main ():
   
try:
        app
= QtGui.QApplication([])
       
print("no problems panning")
   
except RuntimeError:
        app
= QtGui.QApplication.instance()
       
print("panning will flicker-invert when panning")

   
# generate some fake data
    x
= np.arange(-8,8,0.01)
    y
= np.cos(10*x)*np.exp(-np.abs(x))
   
    curve
= pg.PlotCurveItem(x=x,y=y)
    plot_widget
= pg.PlotWidget()
    plot_widget
.plotItem.addItem(curve)
    plot_widget
.show()
    app
.exec_()

main
()




my system information

>>> pg.systemInfo()
sys.platform: darwin
sys.version: 2.7.3 |EPD 7.3-2 (32-bit)| (default, Apr 12 2012, 11:28:34)
[GCC 4.0.1 (Apple Inc. build 5493)]

qt bindings: PySide 1.1.0
pyqtgraph: 0.9.7; None
config:
{'antialias': False,
 'background': (0, 0, 0),
 'editorCommand': None,
 'foreground': (150, 150, 150),
 'leftButtonPan': True,
 'useOpenGL': False,
 'useWeave': True,
 'weaveDebug': False}

Regular View.png
Inverted View.png

Luke Campagnola

unread,
Oct 3, 2013, 11:34:58 AM10/3/13
to pyqt...@googlegroups.com
On Wed, Oct 2, 2013 at 6:19 PM, fox <gregers...@gmail.com> wrote:
I'm experiencing the same problem. Below is some code which recreates the problem. The first time I run it (i.e. when the QApplication is actually instanciated) then the panning/zooming works just fine (attached "Regular View.png") but the second time (i.e. when the QApplication.instance() is used) then when panning/zooming causes the buffer to flicker between regular and inverted (attached "Inverted View.png").



import numpy as np
import pyqtgraph as pg
from pyqtgraph import QtGui, QtCore

def main ():
   
try:
        app
= QtGui.QApplication([])
       
print("no problems panning")
   
except RuntimeError:
        app
= QtGui.QApplication.instance()
       
print("panning will flicker-invert when panning")

   
# generate some fake data
    x
= np.arange(-8,8,0.01)
    y
= np.cos(10*x)*np.exp(-np.abs(x))
   
    curve
= pg.PlotCurveItem(x=x,y=y)
    plot_widget
= pg.PlotWidget()
    plot_widget
.plotItem.addItem(curve)
    plot_widget
.show()
    app
.exec_()

main
()
 
Interesting! In my experience, even attempting to call QtGui.QApplication() multiple times can cause hangups and crashes. What happens if you move that line out to the beginning of the program? Or use app = pg.mkQApp(), which checks whether there is already a QApplicaion instance before attempting to create one:

def mkQApp():
    global QAPP
    inst = QtGui.QApplication.instance()
    if inst is None:
        QAPP = QtGui.QApplication([])
    else:
        QAPP = inst
    return QAPP

 I would also avoid calling app.exec_() more than once if possible. You can make your own event loop by calling QApplication.processEvents() periodically.


Luke

fox

unread,
Oct 28, 2013, 1:16:49 PM10/28/13
to pyqt...@googlegroups.com
Hi,
I tried using the pg.mkQApp but got the same behavior
import numpy as np
import pyqtgraph as pg
from pyqtgraph import QtGui, QtCore

def main ():

    app
= pg.mkQApp()


   
# generate some fake data
    x
= np.arange(-8,8,0.01)

    y
= np.cos(10*x)**2*np.exp(-np.abs(x))


    curve
= pg.PlotCurveItem(x=x,y=y)
    plot_widget
= pg.PlotWidget()
    plot_widget
.plotItem.addItem(curve)
    plot_widget
.show()
    app
.exec_()

main
()

I think app.exec_() needs to be called once after each instance of QApplication. I tried using QApplication.processEvents() to update the plot but something's missing which won't allow for pan/zooming afterwards (Note: I tried threading the processEvents() into a loop called every fraction of a second but that didn't allow for updating the pan/zoom either).


def exec_app ():
    t_finish
= time.time()+60*0.5
   
while  time.time() < t_finish:
       
QtGui.QApplication.processEvents()
        time
.sleep(0.05)
   
print("done updating")

# then put in the lines:
#    thread = threading.Thread(target=exec_app,name='QtAppExec')
#    thread.start()
#    thread.join()
# instead of
#    app.exec_()






On Thursday, October 3, 2013 9:34:58 AM UTC-6, Luke Campagnola wrote:

Luke Campagnola

unread,
Oct 28, 2013, 1:35:56 PM10/28/13
to pyqt...@googlegroups.com
On Mon, Oct 28, 2013 at 1:16 PM, fox <gregers...@gmail.com> wrote:
Hi,
I tried using the pg.mkQApp but got the same behavior
import numpy as np
import pyqtgraph as pg
from pyqtgraph import QtGui, QtCore

def main ():

    app
= pg.mkQApp()


   
# generate some fake data
    x
= np.arange(-8,8,0.01)

    y
= np.cos(10*x)**2*np.exp(-np.abs(x))


    curve
= pg.PlotCurveItem(x=x,y=y)
    plot_widget
= pg.PlotWidget()
    plot_widget
.plotItem.addItem(curve)
    plot_widget
.show()
    app
.exec_()

main
()

I think app.exec_() needs to be called once after each instance of QApplication. I tried using QApplication.processEvents() to update the plot but something's missing which won't allow for pan/zooming afterwards (Note: I tried threading the processEvents() into a loop called every fraction of a second but that didn't allow for updating the pan/zoom either).

I am confused about why you are calling exec() multiple times. Can you rethink the code structure such that exec() is only called once at the beginning of the program, or do you have a specific reason for repeatedly entering and exiting the event loop? The Qt documentation is not clear on this matter, but many people seem to agree that re-entering the event loop is a bad idea:


It is also not advisable to run processEvents (or really do almost anything Qt-related) from any thread except the main thread. 


Luke

fox

unread,
Nov 8, 2013, 11:11:17 PM11/8/13
to pyqt...@googlegroups.com
Hi,

Fair enough. I am re-calling the exec() because of my workflow in developing the gui I'm working on.  I am testing it within a IPython interpreter instead of just calling it from the command line ($python -i <script>). So exec() kept getting called (and needed to be) when I would run it again within the interpreter. For the most part this doesn't seem to give me any problems except in this graphics case.

I think it's obvious this is something to do with Qt (not PyQtGraph). Getting an instance of the QtApp using QtApp.instance() after the main event loop has closed (then starting a new event loop via .exec()), leads to this problem. The solution is just to call it from the command line (so that a new instance of python then runs Qt then quits when Qt is done).

Ok, thank you for your responses and for developing this code!
Reply all
Reply to author
Forward
0 new messages