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