pyQt QWidget 'flicker' 调整大小和重绘
pyQt QWidget 'flicker' on resize and redraw
我正在寻找一种方法来减少我的 pyQt 应用程序上的重绘 'flicker'。
我的应用程序是一个 QMainWindow,其中包含两个 QDockWidget 派生对象(以及常见的工具、菜单和状态栏组合)。其中一个 QDockWidgets* 使用 QGridLayout 在每个网格元素中排列多个派生的 QGLWidget windows。
当我调整 MainWindow 的大小时,整个布局都会正确调整大小。但是,在 QGLWidgets 之间的 space 中,我可以看到 MainWindow 'flick' 某些部分的一些部分呈现的奇怪形状的视图瞬间进入视图,然后正确呈现。我的应用程序通常使用深色样式着色,但 QGLWidgets 之间的闪烁通常只是白色和黑色。我拖动主窗口边框的速度越快,这种闪烁就越明显。让我强调一下,'flicker' 仅在 QGLWidget 对象后面和之间的背景中,其他一切似乎都很好。
无论我在QGLWidgets里有没有画东西,都会有闪烁,所以渲染上的负载并不大。
有什么办法可以消除重绘(和调整大小)事件时的闪烁吗?
我试过将所有小部件涂成相同的深色,在一些小部件上使用 .hide() 和 .show(),但它们似乎只会减慢进程并使情况变得更糟。
- 注意我发现我必须在 QDockWidget 中放置一个虚拟 QWidget,因为 QDockWidget 不接受(我猜它不支持)布局。可能与此有关。
这是针对 python 2.7 运行 Windows 7 的 pyQt 4.10.1。我有大约一个月的 pyQt
经验
所以,按照上述建议,当您移动到 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()
我正在寻找一种方法来减少我的 pyQt 应用程序上的重绘 'flicker'。
我的应用程序是一个 QMainWindow,其中包含两个 QDockWidget 派生对象(以及常见的工具、菜单和状态栏组合)。其中一个 QDockWidgets* 使用 QGridLayout 在每个网格元素中排列多个派生的 QGLWidget windows。
当我调整 MainWindow 的大小时,整个布局都会正确调整大小。但是,在 QGLWidgets 之间的 space 中,我可以看到 MainWindow 'flick' 某些部分的一些部分呈现的奇怪形状的视图瞬间进入视图,然后正确呈现。我的应用程序通常使用深色样式着色,但 QGLWidgets 之间的闪烁通常只是白色和黑色。我拖动主窗口边框的速度越快,这种闪烁就越明显。让我强调一下,'flicker' 仅在 QGLWidget 对象后面和之间的背景中,其他一切似乎都很好。
无论我在QGLWidgets里有没有画东西,都会有闪烁,所以渲染上的负载并不大。
有什么办法可以消除重绘(和调整大小)事件时的闪烁吗?
我试过将所有小部件涂成相同的深色,在一些小部件上使用 .hide() 和 .show(),但它们似乎只会减慢进程并使情况变得更糟。
- 注意我发现我必须在 QDockWidget 中放置一个虚拟 QWidget,因为 QDockWidget 不接受(我猜它不支持)布局。可能与此有关。
这是针对 python 2.7 运行 Windows 7 的 pyQt 4.10.1。我有大约一个月的 pyQt
经验所以,按照上述建议,当您移动到 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()