Qt:QTabWidget导致不必要的重绘

时间:2014-04-28 10:27:10

标签: qt pyqt pyside

我发现QTabWidget在重绘孩子方面表现出一种非常奇怪的行为。以下代码是我为观察此问题而创建的最小示例。

假设我有一个自定义小部件(绘图),它具有昂贵的绘制事件hadler。所以我需要尽量减少重新绘制的次数。但问题是如果这个绘图小部件在QTabWidget中,它会收到许多不必要的重绘请求,作为对其他一些完全不相关的小部件(在下面的示例中 - 按钮和标签)的更改的响应。

在示例的最后,您可以更改变量withTabWidget。如果设置为True,则每次按下按钮时都会重新绘制图形(即图形中的数字会增加)。如果设置为False,则按下按钮时不会重新绘制图形(图形中的数字保持不变),这是我需要的正确行为。但显然,我还需要在我的应用布局中使用选项卡小部件......

任何想法如何使标签窗口小部件正常工作,没有不必要的重新绘制?

注意:Qt 4.8.4(在32位和64位上测试),PySide 1.2.1。,Windows 7

import sys
from PySide import QtGui


class MyDrawing(QtGui.QLabel):
    # drawing is a widget which has user defined paint event handler
    # the painting can be costly so we must avoid unnecessary repainting

    repaintCount = 0

    def paintEvent(self, event):
        # a very simple example which count ...
        # the number of times the paintEvent was executed
        self.repaintCount += 1
        painter = QtGui.QPainter(self)
        painter.drawText(10, 10, str(self.repaintCount))


class MyContainer(QtGui.QWidget):

    def __init__(self, parent=None):
        super(MyContainer, self).__init__(parent)
        layout = QtGui.QHBoxLayout(self)

        # there is a button ...
        self.button = QtGui.QPushButton("Press me.")
        self.button.setCheckable(True)
        self.button.pressed.connect(self.onButtonPressed)
        layout.addWidget(self.button)

        # .. and a label ...
        self.label = QtGui.QLabel()
        layout.addWidget(self.label)

        # ... and a drawing
        self.drawing = MyDrawing()
        layout.addWidget(self.drawing)

    def onButtonPressed(self):
        # pressing button only changes the label
        # it does not change the drawing 
        # so drawing should not be repainted
        # but when the container is inside QTabWidget it IS repainted
        self.label.setText(str(self.button.isChecked()))


if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    form = QtGui.QMainWindow()

    # change this True/False!!!
    withTabWidget = True
    # True = problem: MyDrawing IS repainted when button1 is pressed
    # False = OK: MyDrawing IS NOT repainted when button1 is pressed
    if withTabWidget:
        tabWidget = QtGui.QTabWidget()
        tabWidget.addTab(MyContainer(), "Tab1")
        form.setCentralWidget(tabWidget)
    else:
        form.setCentralWidget(MyContainer())

    form.show()
    result = app.exec_()
    sys.exit(result)

更新:通过跟踪QTabWidget上的事件,我发现,当标签被更改时,会在QTabWidget中插入一些动画对象(添加子项)。 QTabWidget通过重新绘制它覆盖的整个区域来响应。这与其他窗口小部件类型不同,当插入动画对象时,它不会重绘其整个区域。不幸的是,我仍然没有解决方法。也许我会不惜一切代价制作我自己的TabWidget。

Update2:另一个有趣的方面是,当我使用QTabWidget启动上面的示例应用程序时,绘图中绘制的数字是2.当我在没有QTabWidget的情况下启动它时,数字是1.所以它是另一个示例不必要的重新粉刷。

0 个答案:

没有答案