1

Im looking for a way to minimize redraw 'flicker' on my pyQt app.

My app is a QMainWindow containing two QDockWidget derived objects (and the usual assortment of tool. menu and statusbars). One of the QDockWidgets* uses a QGridLayout to arrange a number of QGLWidget derived windows in each grid element.

When I resize the MainWindow, the entire arrangement resizes correctly. However, in the space between the QGLWidgets I can see what looks like some partially rendered oddly-shaped view of some part of the MainWindow 'flick' into view for a split second and then render correctly. My app is generally colored with dark styles but that flicker in between the QGLWidgets is usually just white and black. The faster I drag the Mainwindow borders, the more pronounced this flicker. And let me emphasize, the 'flicker' is only in the background behind and between the QGLWidget objects, everything else seems fine.

The flicker is there whether I have anything painted in the QGLWidgets or not, so there isn't a heavy load on the rendering.

Is there something I can do to eliminate this flicker on repaint (and resize) events?

I've tried coloring all the widgets the same dark color, played with .hide() and .show() on some of the widgets, but they just seem to slow the process down and make it worse.

  • NOTE I found I had to put a dummy QWidget in the QDockWidget as the QDockWidget wouldn't accept (I guess it doesn't support) Layouts. Maybe that has something to do with this.

This is with pyQt 4.10.1 for python 2.7 running on Windows 7. I have about a months experience with pyQt

thefog
  • 181
  • 1
  • 4
  • 13
  • Sounds very similar to [QTBUG-17869](https://bugreports.qt.io/browse/QTBUG-17869) and [QTBUG-38327](https://bugreports.qt.io/browse/QTBUG-38327). – ekhumoro Feb 08 '15 at 02:34
  • I looked over those bug reports, thanks, looks like its the same bug as mine and has to do with QGLWidget. Very dis-heartening ! I get the impression that the bug is fixed in pyQt5 and to recommend using QOpenGLWidget. I'm not too keen to migrate to Qt5 yet, my code uses old style Signals and slots for one, until I know it really is fixed - does anybody know for sure ? – thefog Feb 08 '15 at 15:02
  • 1
    You don't have to port your whole application to PyQt5 to test it. Just create a minimal, self-contained example script that reproduces the problem in PyQt4, then convert it to PyQt5. If you don't know how to port it, or can't install PyQt5 for some reason, post the example script here, and either I or someone else can do the necessary testing. – ekhumoro Feb 08 '15 at 18:09
  • looks like pyQt5 is out of consideration for the moment for us, we are stuck with python 2.7 for a while (dependency on other libraries). Im still hoping there is some kind of workaround, anything, that people have come up with. Anyone experienced this problem with pySide ? – thefog Feb 09 '15 at 12:57
  • It's a Qt bug, not a PyQt/PySide bug. As for workarounds: just do some searching on the web - you'll find plenty of suggestions (but don't expect any miracles). – ekhumoro Feb 09 '15 at 17:55

1 Answers1

1

SO, following the above advice, the flicker DOES go away when you move to PyQt5 and Python34 and use the new QtWidgets.QOpenGLWidget. You can run the code below that using the new widget and the flicker is gone, but with the old QGLWidget (####lines), the background refreshes are quite annoying during a resize.

from PyQt5 import QtCore, QtGui, QtWidgets, QtOpenGL

class ImageGLView ( QtWidgets.QOpenGLWidget ):
####class ImageGLView ( QtOpenGL.QGLWidget ):   

    def __init__(self, parent = None ):
        print ( "ImageGLView.__init__" )

        QtWidgets.QOpenGLWidget.__init__( self, parent )
        ####QtOpenGL.QGLWidget.__init__( self, QtOpenGL.QGLFormat( QtOpenGL.QGL.SampleBuffers), parent )

        self.setStyleSheet( "QtOpenGL.QGLWidget {border-style: None; background-color: #404040; color:#FFFFFF }" )
        self.setToolTip ( "Image View" )


class TopWindow(QtWidgets.QMainWindow):
    def __init__ ( self, parent = None ):
        super( TopWindow, self).__init__(parent)

        self.initUI()
        self.initStyle()

    def initUI (self):
        self.setGeometry ( 0, 0, 800, 600 )
        self.setWindowTitle ( 'Test pyQt5')
        self.setWindowIcon ( QtGui.QIcon( 'images\Curlyhoward.jpg' ) )
        self.setStyleSheet("QWidget {background-color: #404040; color:#FFFFFF }" )
        self.populateFrames()


    def initStyle(self):
        palette = self.palette()
        palette.setColor(self.backgroundRole(), QtGui.QColor(64,64,64) )
        self.setToolTip( "Liver Fat Fraction")
        self.setPalette(palette )

        self.setDockOptions(QtWidgets.QMainWindow.AnimatedDocks | QtWidgets.QMainWindow.AllowNestedDocks)


    def populateFrames(self ):       
        self.controlsPane = QtWidgets.QDockWidget()
        self.controlsPane.setFeatures(QtWidgets.QDockWidget.DockWidgetFloatable | QtWidgets.QDockWidget.DockWidgetMovable)
        self.controlsPane.setAllowedAreas( QtCore.Qt.LeftDockWidgetArea | QtCore.Qt.RightDockWidgetArea )
        self.controlsPane.setStyleSheet("QWidget {background-color: #404040; color:#FFFFFF }" )        
        self.addDockWidget( QtCore.Qt.RightDockWidgetArea, self.controlsPane )     

        self.imageDisplayPane = QtWidgets.QDockWidget()
        self.imageDisplayPane.setFeatures(QtWidgets.QDockWidget.DockWidgetFloatable | QtWidgets.QDockWidget.DockWidgetMovable)
        self.imageDisplayPane.setAllowedAreas( QtCore.Qt.RightDockWidgetArea | QtCore.Qt.LeftDockWidgetArea | QtCore.Qt.TopDockWidgetArea | QtCore.Qt.BottomDockWidgetArea )
        self.imageDisplayPane.setStyleSheet("QWidget {background-color: #FAFAFA; color:#0f0f0f }" )        

        numCols = 2
        numRows = 2

        self.imageDisplayPane.gridLayout = QtWidgets.QGridLayout()      

            #### ...seems like a QDockWidget needs to have a single widget in which it can then accept the layout...
            self.imageDisplayPane.paneContent = QtWidgets.QWidget()
            self.imageDisplayPane.paneContent.setStyleSheet("QWidget {background-color: #404040; color:#FFFFFF }" )
            self.imageDisplayPane.setWidget( self.imageDisplayPane.paneContent )            
            self.imageDisplayPane.paneContent.setLayout( self.imageDisplayPane.gridLayout )                                                                                

            for row in range ( numRows ):
                for col in range ( numCols ):                
                    view = ImageGLView( self )
                    self.imageDisplayPane.gridLayout.addWidget (view, row, col )                        
            self.addDockWidget( QtCore.Qt.LeftDockWidgetArea, self.imageDisplayPane )    


def main():
    app = QtWidgets.QApplication( sys.argv )
    app.setStyle ( "windows ")

    mainWindow = TopWindow()
    mainWindow.show()

    mainWindow.raise_()
    app.exec_()


if __name__ == '__main__':
    main()
thefog
  • 181
  • 1
  • 4
  • 13
  • BTW, installing and configuring PyQt5 on eclipse was not as straightforward as the older python 2.7/pyQt4. – thefog Feb 10 '15 at 22:10
  • Glad you followed through on this and made some progress. I just thought I'd add that, AFAIK, it should still be possible to build PyQt5 for Python2. Even so, as I pointed out in [this answer](http://stackoverflow.com/a/22802900/984421), it's probably not a viable long-term option. – ekhumoro Feb 10 '15 at 23:49