我在运行时更新循环中的标签时遇到问题。我想我需要使用信号等等,但我已经尝试过我能想到的一切。我希望我的程序能做什么:
当我点击按钮时,循环应该开始运行一些需要一些时间的功能。当函数运行时,相应的标签应更新其文本以说明"运行"当它完成时应该说"完成"并继续下一个功能。我已经创建了一些代表我之后的虚拟代码!
我用虚拟函数表示我的函数只需要一些时间。
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_())
答案 0 :(得分:1)
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))
答案 1 :(得分:0)
更简单的方法是调用QApplication.processEvents()来强制QT处理队列中存在的所有事件。但是UI不会像其他线程那样响应,就像其他答案中所说的那样,工作并向主线程发送信号。