Qt5 paintEvent 传播到子小部件

Posted

技术标签:

【中文标题】Qt5 paintEvent 传播到子小部件【英文标题】:Qt5 paintEvent propagation to child widgets 【发布时间】:2017-06-30 06:06:19 【问题描述】:

我正在尝试在 PyQt5 中编写一个基本的游戏循环。我里面有一个QWidget 和一个QGraphicsView。我使用QTimerupdate()QWidgetQGraphicsView 上触发paintEvent()QWidget paintEvent() 得到更新,但 QGraphicsView paintEvent() 没有。

这是我的代码:

import sys, random

from PyQt5.QtWidgets import QWidget, QGridLayout, QApplication, QGraphicsView, QGraphicsScene
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtGui import QPainter, QColor, QPen, QBrush, QColor



class Window(QWidget):

    WIDTH = 800
    HEIGHT = 480
    SPEED = 500

    def __init__(self):

        super().__init__()
        self.initUi()
        self.initDisplay()
        self.show()

    def initUi(self):

        layout = QGridLayout()

        scene = GraphicsScene()        
        self.view = GraphicsView()
        self.view.setScene(scene)

        layout.addWidget(self.view)
        self.setLayout(layout)


    def initDisplay(self):     

        self.resize(Window.WIDTH, Window.HEIGHT)

        self.timer = QTimer()
        self.timer.setInterval(Window.SPEED)
        self.timer.timeout.connect(self.timerEvent)
        self.isStarted = False
        self.isPaused = False

        self.timer.start()


    def start(self):

        if self.isPaused:
            return

        self.isStarted = True
        self.timer.start(Display.SPEED)


    def pause(self):

        if not self.isStarted:
            return

        self.isPaused = not self.isPaused

        if self.isPaused:
            self.timer.stop()            
        else:
            self.timer.start(Display.SPEED)

        self.update()


    def paintEvent(self, event):
        print('paint event ...')


    def timerEvent(self):
        self.update()
        self.view.update()
        print('timer event ...')



class GraphicsView(QGraphicsView):


    def __init__(self):
        super(GraphicsView, self).__init__()


    def paintEvent(self, event):
        self.scene().add_shapes()
        print('view paint event')



class GraphicsScene(QGraphicsScene):

    def __init__(self):
        super(GraphicsScene, self).__init__()


    def add_shapes(self):

        self.setSceneRect(0.0, 0.0, 800.0, 640.0)

        self.addRect(100, 100, 150, 150)

        pen = QPen(Qt.SolidLine)
        pen.setColor(Qt.red)
        brush = QBrush(Qt.Dense3Pattern)
        brush.setColor(Qt.darkGreen)
        self.addEllipse(300, 300, 100, 100, pen, brush)
        print('add shapes')        



if __name__ == '__main__':

    app = QApplication([])
    window = Window()    
    sys.exit(app.exec_())

当我运行脚本时,我得到以下输出:

paint event ...
add shapes
view paint event
paint event ...
add shapes
view paint event
timer event ...
paint event ...
paint event ...
timer event ...
paint event ...
paint event ...
timer event ...
paint event ...
paint event ...
timer event ...
paint event ...
paint event ...
timer event ...
paint event ...
paint event ...

【问题讨论】:

【参考方案1】:

解决办法是调用基类的paintEvent()(本例为QGraphicsView

import sys, random

from PyQt5.QtWidgets import QWidget, QGridLayout, QApplication, QGraphicsView, QGraphicsScene
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtGui import QPainter, QColor, QPen, QBrush, QColor



class Window(QWidget):

    WIDTH = 800
    HEIGHT = 480
    SPEED = 500

    def __init__(self):

        super().__init__()
        self.initUi()
        self.initDisplay()
        self.show()

    def initUi(self):

        layout = QGridLayout()

        self.scene = GraphicsScene()
        self.view = GraphicsView(self, self.scene)

        layout.addWidget(self.view)
        self.setLayout(layout)


    def initDisplay(self):     

        self.resize(Window.WIDTH, Window.HEIGHT)

        self.timer = QTimer()
        self.timer.setInterval(Window.SPEED)
        self.timer.timeout.connect(self.timerEvent)
        self.isStarted = False
        self.isPaused = False

        self.timer.start()


    def start(self):

        if self.isPaused:
            return

        self.isStarted = True
        self.timer.start(Display.SPEED)


    def pause(self):

        if not self.isStarted:
            return

        self.isPaused = not self.isPaused

        if self.isPaused:
            self.timer.stop()            
        else:
            self.timer.start(Display.SPEED)

        self.update()


    def paintEvent(self, event):
        print('paint event ...')


    def timerEvent(self):
        self.update()
        self.view.update()
        self.scene.update()
        print('timer event ...')



class GraphicsView(QGraphicsView):


    def __init__(self, parent, scene):

        super(GraphicsView, self).__init__()
        self.scene = scene   
        self.parent = parent
        self.setScene(self.scene)


    def paintEvent(self, event):
        QGraphicsView.paintEvent(self, event)#########
        self.setScene(self.scene)
        self.scene.add_shapes()
        print('view paint event')



class GraphicsScene(QGraphicsScene):

    def __init__(self):
        super(GraphicsScene, self).__init__()


    def add_shapes(self):

        self.setSceneRect(0.0, 0.0, 700.0, 450.0)

        self.addRect(100, 100, 150, 150)

        pen = QPen(Qt.SolidLine)
        pen.setColor(Qt.red)
        brush = QBrush(Qt.Dense3Pattern)
        brush.setColor(Qt.darkGreen)
        self.addEllipse(300, 300, 100, 100, pen, brush)
        print('add shapes')        



if __name__ == '__main__':

    app = QApplication([])
    window = Window()    
    sys.exit(app.exec_())

【讨论】:

以上是关于Qt5 paintEvent 传播到子小部件的主要内容,如果未能解决你的问题,请参考以下文章

将组件添加到子小部件后调整 QDialog 的大小

在可扩展浮动操作按钮中,在颤动中未检测到子小部件中的手势

具有重叠子小部件的 Qt 自定义小部件

在子创建后设置父时,子小部件对事件是透明的

由父级绘制 QWidget

Qt5 paintEvent() 区域太小