PyQT5 - 使用暂停逐个添加行

时间:2017-12-26 18:07:40

标签: python pyqt5 sleep

以下代码每隔一秒钟绘制一条随机行。我想做的是保持每条线都已画出来。最好的方法是什么?

我知道我需要使用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_())

2 个答案:

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