【问题标题】:pyQt QWidget 'flicker' on resize and redrawpyQt QWidget在调整大小和重绘时“闪烁”
【发布时间】:2015-04-08 00:09:05
【问题描述】:

我正在寻找一种方法来最小化我的 pyQt 应用上的重绘“闪烁”。

我的应用程序是一个 QMainWindow,其中包含两个 QDockWidget 派生对象(以及通常的各种工具、菜单和状态栏)。其中一个 QDockWidgets* 使用 QGridLayout 在每个网格元素中排列多个 QGLWidget 派生窗口。

当我调整 MainWindow 的大小时,整个排列都会正确调整大小。但是,在 QGLWidgets 之间的空间中,我可以看到 MainWindow 某些部分的某些部分渲染的奇怪形状的视图在瞬间“轻弹”进入视图,然后正确渲染。我的应用程序通常以深色样式着色,但 QGLWidgets 之间的闪烁通常只是白色和黑色。我拖动主窗口边框的速度越快,这种闪烁就越明显。让我强调一下,“闪烁”仅在 QGLWidget 对象后面和之间的背景中,其他一切似乎都很好。

无论我是否在 QGLWidgets 中绘制了任何内容,都会出现闪烁,因此渲染的负载并不大。

我能做些什么来消除重绘(和调整大小)事件时的这种闪烁吗?

我尝试将所有小部件着色为相同的深色,在某些小部件上使用 .hide() 和 .show() 进行播放,但它们似乎只是减慢了进程并使其变得更糟。

  • 注意我发现我必须在 QDockWidget 中放置一个虚拟 QWidget,因为 QDockWidget 不接受(我猜它不支持)布局。也许这与此有关。

这是用于在 Windows 7 上运行的 python 2.7 的 pyQt 4.10.1。我有大约一个月的 pyQt 经验

【问题讨论】:

  • 听起来很像QTBUG-17869QTBUG-38327
  • 我查看了那些错误报告,谢谢,看起来和我的错误相同,并且与 QGLWidget 有关。非常令人沮丧!我的印象是该错误已在 pyQt5 中修复,并建议使用 QOpenGLWidget。我还不太热衷于迁移到 Qt5,我的代码使用旧式信号和插槽,直到我知道它确实是固定的 - 有人确定吗?
  • 您不必将整个应用程序移植到 PyQt5 来测试它。只需创建一个最小的、独立的示例脚本,在 PyQt4 中重现问题,然后将其转换为 PyQt5。如果您不知道如何移植它,或者由于某种原因无法安装 PyQt5,请在此处发布示例脚本,我或其他人都可以进行必要的测试。
  • 看起来 pyQt5 暂时不适合我们,我们暂时使用 python 2.7(依赖于其他库)。我仍然希望人们想出某种解决方法,任何东西。有人用 pySide 遇到过这个问题吗?
  • 这是一个 Qt 错误,而不是 PyQt/PySide 错误。至于解决方法:只需在网络上进行一些搜索 - 你会发现很多建议(但不要指望任何奇迹)。

标签: python qt pyqt flicker qdockwidget


【解决方案1】:

所以,按照上述建议,当您迁移到 PyQt5 和 Python34 并使用新的 QtWidgets.QOpenGLWidget 时,闪烁确实会消失。您可以使用新的小部件运行下面的代码并且闪烁消失了,但是使用旧的 QGLWidget (####lines),在调整大小期间背景刷新非常烦人。

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()

【讨论】:

  • 顺便说一句,在 Eclipse 上安装和配置 PyQt5 并不像旧的 python 2.7/pyQt4 那样简单。
  • 很高兴您坚持了这一点并取得了一些进展。我只是想补充一点,AFAIK,应该仍然可以为 Python2 构建 PyQt5。即便如此,正如我在this answer 中指出的那样,这可能不是一个可行的长期选择。
猜你喜欢
  • 1970-01-01
  • 2016-03-19
  • 1970-01-01
  • 2015-01-24
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-11
相关资源
最近更新 更多