PDA

View Full Version : I'm trying to write a QPainter update Interval



yskioi
19th June 2020, 17:23
I'm going to use the QPainter update to make the shape appear and hit, but if I run the thread, it won't come up. What's wrong with it?
the part of a problem
while not e.wait(1):
self.update()



import sys
from PyQt5.QtWidgets import QWidget, QApplication , QPushButton, QVBoxLayout
from PyQt5.QtGui import QPainter, QPen, QColor, QBrush
from PyQt5.QtCore import Qt
import numpy as np

import threading

class MyApp(QWidget):

def __init__(self):
super().__init__()
self.initUI()

def initUI(self):
self.setGeometry(300, 300, 400, 400)
self.setWindowTitle('Rect')
self.show()

def paintEvent(self, e):
qp = QPainter()
qp.begin(self)
self.draw_rect(qp)
e = threading.Event()
#the part of a problem
while not e.wait(1):
self.update()
qp.end()


def draw_rect(self, qp):
qp.setBrush(QColor(0, 0, 0))
for i in range(5):
rand_x = 100 * np.random.randn()
rand_y = 100 * np.random.randn()
qp.drawRect(self.width() / 2 + rand_x, self.height() / 2 + rand_y, 10, 10)



if __name__ == '__main__':
app = QApplication(sys.argv)
ex = MyApp()
sys.exit(app.exec_())

d_stranz
19th June 2020, 18:50
In Qt, all GUI updates have to occur in the main thread. You can't implement drawing operations in a different thread. You also can't do anything in a paint event which will trigger another paint event (like call update or resize the widget, etc.). And finally, paint event handling is optimized to eliminate unnecessary repainting. If nothing has changed to require repainting, or if there are several paint events in the event queue, only the last one will be executed and the rest discarded.

All on-screen QWidget painting is event driven, and you can only create a QPainter and draw during a paintEvent().

In any case, this is the wrong way to go about it. If you want something to happen at given intervals, you implement a QTimer, and connect a slot to the QTimer::timeout() signal. In the slot, make the changes you want, then call update() (or if you have changed a widget property that triggers an update, like resizing, the widget will probably repaint itself).

Finally, if you construct your QPainter instance with "self" as the argument, you do not need to call QPainter::begin() / QPainter::end(). When you use this constructor (qp = QPainter( self )), it calls begin() inside the constructor, and end() when it is destroyed when the paintEvent() exits.

yskioi
16th July 2020, 13:44
The problem has been solved. Thank you.