Python PyQt5:在运行时更新标签

Python PyQt5:在运行时更新标签,python,pyqt,pyqt5,qlabel,Python,Pyqt,Pyqt5,Qlabel,在运行时更新循环中的标签时出现问题。我想我需要使用信号等等,但我现在已经尝试了我能想到的一切。我希望我的程序执行的操作: 当我点击按钮时,应该会启动一个循环,运行一些需要一些时间的函数。当函数运行时,相应的标签应更新其文本为“running”,完成后应为“done”,并继续下一个函数。我已经创建了一些表示我所追求的东西的伪代码 我已经用一个伪函数表示了我的函数,它只需要一些时间 import sys from PyQt5.QtWidgets import * import time class

在运行时更新循环中的标签时出现问题。我想我需要使用信号等等,但我现在已经尝试了我能想到的一切。我希望我的程序执行的操作:

当我点击按钮时,应该会启动一个循环,运行一些需要一些时间的函数。当函数运行时,相应的标签应更新其文本为“running”,完成后应为“done”,并继续下一个函数。我已经创建了一些表示我所追求的东西的伪代码

我已经用一个伪函数表示了我的函数,它只需要一些时间

import sys
from PyQt5.QtWidgets import *
import time

class Example(QWidget):

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

        self.initUI()


    def initUI(self):
        # Set up an example ui
        qbtn = QPushButton('Click', self)
        qbtn.clicked.connect(self.changeLabels)
        qbtn.resize(qbtn.sizeHint())
        qbtn.move(100, 50)
        # Add labels
        self.labels = list()
        self.labels.append(QLabel("Lbl1", self))
        self.labels[-1].setFixedSize(50, 20)
        self.labels.append(QLabel("Lbl2", self))
        self.labels[-1].setFixedSize(50, 20)
        self.labels[-1].move(0, 20)
        self.labels.append(QLabel("Lbl3", self))
        self.labels[-1].setFixedSize(50, 20)
        self.labels[-1].move(0, 40)

        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('Test')
        self.show()

    def changeLabels(self):
        # Loop over all labels. For each label a function will be executed that will take some time. In this case
        # I represent that with a dummy function to just take time. While the function is running the label should say
        # "running" and when its finished it should say "done".
        for lbl in self.labels:
            orgTxt = lbl.text()
            lbl.setText("%s Running" % orgTxt)
            self.dummyFunction()
            lbl.setText("%s Done" % orgTxt)

    def dummyFunction(self):
        time.sleep(1)


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

GUI不支持阻塞任务,因为GUI需要一些时间来更新窗口的某些属性,一个可能的解决方案是使用新线程并实现虚拟函数,在下面的示例中,使用信号显示了实现。如果您的实际函数更新了任何GUI视图,那么您不应该直接在线程中进行更新,而应该通过信号进行更新

class DummyThread(QThread):
    finished = pyqtSignal()
    def run(self):
        time.sleep(1)
        self.finished.emit()

class Example(QWidget):
    [...]
    def changeLabels(self):
        for lbl in self.labels:
            orgTxt = lbl.text()
            lbl.setText("%s Running" % orgTxt)
            thread = DummyThread(self)
            thread.start()
            thread.finished.connect(lambda txt=orgTxt, lbl=lbl : lbl.setText("%s Done" % txt))

一种更简单的方法是调用QApplication.processEvents()来强制QT处理队列中存在的所有事件。但是UI不会像其他回答中所述的那样,在另一个线程完成工作并向主线程发送信号的情况下,UI的响应性会更好

您需要在另一个线程中运行函数,并通过signal/slot更新文本。