以下代码每隔一秒钟绘制一条随机行。我想做的是保持每条线都已画出来。最好的方法是什么?
我知道我需要使用QTimer
来做响应式用户界面,但首先我需要知道如何绘制越来越多的行......
也许有一种方法可以隐藏所有线条并显示越来越多的线条......或者我必须使用QGraphicsView
吗?
from random import random
import sys
from time import sleep
from PyQt5.QtWidgets import QWidget, QApplication
from PyQt5.QtGui import QPainter
from PyQt5.QtCore import QTimer
LINES = [
(500*random(), 500*random(), 500*random(), 500*random())
for _ in range(50)
]
class Interface(QWidget):
def __init__(self):
super().__init__()
self.max = len(LINES)
self.cursor = 0
self.painter = QPainter()
self.setFixedSize(500, 500)
self.show()
def paintEvent(self, e):
self.painter.begin(self)
self.drawsetpbystep()
self.painter.end()
def drawsetpbystep(self):
if self.cursor < self.max:
self.painter.drawLine(*LINES[self.cursor])
self.update()
sleep(0.25)
self.cursor += 1
if __name__ == '__main__':
app = QApplication(sys.argv)
interface = Interface()
sys.exit(app.exec_())
答案 0 :(得分:1)
建议不要在PyQt应用程序中使用time.sleep
,因为它会阻止Qt事件循环的执行,该循环负责处理用户输入(通过键盘和鼠标)并实际绘制应用程序窗口。
相反,您应该使用QTimer
来计划在您想要的时间执行指定的方法。在这种情况下,您可能希望使用多个QTimer.singleShot
调用。可能由计时器调用的第一个方法将绘制一个点/线,然后设置一个计时器来调用另一个方法,该方法将绘制一个点/线并设置一个计时器来调用另一个方法......等。等
答案 1 :(得分:1)
不建议在GUI中使用sleep,而在PyQt中则非常危险,因为Qt提供了与QTimer,QEventLoop等产生相同效果的替代方案。
另一个错误是QPainter的生命周期非常大,只应在paintEvent中创建和调用。
最后一个错误是想要暂停paintEvent的任务,因为你是通过drawsetpbystep方法完成的。 paintEvent方法不仅会使用它,而且实际上只要你需要它就会使用它,正确的做法是使用一个标志来指示你应该如何绘制,如下所示:
LINES = [
(500*random(), 500*random(), 500*random(), 500*random())
for _ in range(50)
]
class Interface(QWidget):
def __init__(self):
super().__init__()
self.max = len(LINES)
self.cursor = 0
self.show()
self.paint = False
timer = QTimer(self)
timer.timeout.connect(self.onTimeout)
timer.start(250)
def paintEvent(self, e):
painter = QPainter(self)
if self.paint:
self.drawsetpbystep(painter)
def onTimeout(self):
self.paint = True
self.update()
def drawsetpbystep(self, painter):
if self.cursor < self.max:
painter.drawLine(*LINES[self.cursor])
self.cursor += 1
self.paint = False
if __name__ == '__main__':
app = QApplication(sys.argv)
interface = Interface()
sys.exit(app.exec_())