如何在PyQt5的QThread中实现特定数值时更新QLabel内容?
解决PyQt5工作线程中特定条件下更新QLabel的问题
不用修改主类结构、不用将runInThread移入Worker类的run()方法,有两种低成本实现方式:
方式一:使用QMetaObject.invokeMethod线程安全更新UI
直接在runInThread函数中,当计数满足条件时,通过QMetaObject.invokeMethod在主线程调用QLabel的setText方法,避免跨线程操作UI的问题:
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QPushButton from PyQt5.QtCore import QThread, QMetaObject, Qt, Q_ARG import sys import time class MainWindow(QMainWindow): def __init__(self): super().__init__() self.time1 = QLabel("number", self) self.time1.move(50, 50) self.btn = QPushButton("Start", self) self.btn.move(50, 100) self.btn.clicked.connect(self.start_thread) def start_thread(self): self.thread = QThread() self.thread.started.connect(self.runInThread) self.thread.start() def runInThread(self): for c in range(51): time.sleep(0.1) # 模拟长耗时操作 if c in (20, 30): # 线程安全更新QLabel文本 QMetaObject.invokeMethod( self.time1, "setText", Qt.QueuedConnection, Q_ARG(str, f"当前计数: {c}") ) self.thread.quit() self.thread.wait() if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())
方式二:通过自定义信号触发UI更新
在主类中定义一个信号,连接到QLabel的setText方法,然后在runInThread中满足条件时发射信号:
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QPushButton from PyQt5.QtCore import QThread, pyqtSignal import sys import time class MainWindow(QMainWindow): # 定义更新标签的信号 update_label_signal = pyqtSignal(str) def __init__(self): super().__init__() self.time1 = QLabel("number", self) self.time1.move(50, 50) # 连接信号到QLabel的setText方法 self.update_label_signal.connect(self.time1.setText) self.btn = QPushButton("Start", self) self.btn.move(50, 100) self.btn.clicked.connect(self.start_thread) def start_thread(self): self.thread = QThread() self.thread.started.connect(self.runInThread) self.thread.start() def runInThread(self): for c in range(51): time.sleep(0.1) # 模拟长耗时操作 if c in (20, 30): # 发射信号更新标签 self.update_label_signal.emit(f"当前计数: {c}") self.thread.quit() self.thread.wait() if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())
两种方式都只需要对runInThread函数和主类做少量修改,完全不用重构现有大量函数,满足你的需求。
内容的提问来源于stack exchange,提问作者Orca
相关产品推荐
相关产品推荐

