Anonimista
Anonimista

Reputation: 183

Qt5 paintEvent propagation to child widgets

I am trying to write a basic game loop in PyQt5. I have a QWidget and a QGraphicsView inside it. I use QTimer and update() to trigger the paintEvent() on QWidget and QGraphicsView. The QWidget paintEvent() gets updated but QGraphicsView paintEvent() does not.

Here is my code:

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_())

When I run the script I get the following output:

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 ...

Upvotes: 1

Views: 1106

Answers (1)

Anonimista
Anonimista

Reputation: 183

The solution is to call the paintEvent() of the base class (in this case 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_())

Upvotes: 1

Related Questions