2015-02-08 467 views
1

我正在寻找一种方法来最大限度地减少我的pyQt应用程序重绘'闪烁'。我的应用程序是一个QMainWindow,它包含两个QDockWidget派生对象(以及工具菜单和状态栏的常见分类组成)。其中一个QDockWidgets *使用QGridLayout在每个网格元素中排列许多QGLWidget派生的窗口。pyQt QWidget'闪烁'在调整大小和重绘

当我调整MainWindow的大小时,整个安排正确调整大小。然而,在QGLWidgets之间的空间中,我可以看到看起来有些部分呈现的奇怪形状的视图,其中一部分MainWindow在屏幕上“轻弹”,然后正确渲染。我的应用程序通常使用黑色风格着色,但QGLWidgets之间的闪烁通常只是白色和黑色。拖动主窗口边框的速度越快,这种闪烁就越明显。让我强调一下,'闪烁'只是在QGLWidget对象后面和背后的背景中,其他一切似乎都很好。

无论我是否在QGLWidgets中绘制了任何东西,闪烁都在那里,因此渲染没有沉重的负担。

有什么我可以做的,以消除重新绘制(和调整大小)事件的闪烁?

我已经尝试着将所有的小部件着色成相同的深色,在一些小部件上使用.hide()和.show()来玩,但它们似乎只是减缓了过程并使其变得更糟。

  • 注意,我发现我不得不把一个虚拟的QWidget在QDockWidget作为QDockWidget不会接受(我猜它不支持)布局。也许这与此有关。

这是PyQt的4.10.1的Python 2.7在Windows 7上运行我对与PyQt的一个月经验

+0

听起来非常类似于[QTBUG-17869](https://bugreports.qt.io/browse/QTBUG-17869)和[QTBUG-38327](https://bugreports.qt.io/browse/QTBUG-38327)。 – ekhumoro 2015-02-08 02:34:54

+0

我查看了那些错误报告,谢谢,看起来像它和我的一样,并且与QGLWidget有关。非常令人沮丧!我得到的印象是这个bug在pyQt5中得到了解决,并推荐使用QOpenGLWidget。我不太愿意迁移到Qt5,但我的代码使用旧式Signals和插槽,直到我知道它确实是固定的 - 有人知道吗? – thefog 2015-02-08 15:02:39

+1

您不必将整个应用程序移植到PyQt5来测试它。只需创建一个最小化的,自包含的示例脚本,在PyQt4中再现问题,然后将其转换为PyQt5。如果您不知道如何移植它,或者由于某种原因无法安装PyQt5,请在此处发布示例脚本,并且我或其他人都可以执行必要的测试。 – ekhumoro 2015-02-08 18:09:11

回答

1

SO,按照上述建议,闪烁DOES消失,当你移动到PyQt5和Python34并使用新的QtWidgets.QOpenGLWidget。你可以运行下面的代码,使用新的小部件,闪烁消失,但与旧的QGLWidget(####线),背景刷新是非常恼人的调整大小。

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

顺便说一句,在eclipse上安装和配置PyQt5并不像旧版python 2.7/pyQt4那么简单。 – thefog 2015-02-10 22:10:18

+0

很高兴你通过这个并取得了一些进展。我只是想我会补充说,AFAIK,它应该仍然可以为Python2构建PyQt5。即便如此,正如我在[这个答案](http://stackoverflow.com/a/22802900/984421)中指出的那样,这可能不是一个可行的长期选择。 – ekhumoro 2015-02-10 23:49:39