2015-02-08 82 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