Python中QProgressBar结合QThread无法正常工作的原因咨询
QThread结合QProgressBar的UI阻塞问题解析
尝试用QThread实现QProgressBar的动态更新功能,但代码运行后所有操作都在主线程执行,UI完全阻塞。以下是问题代码:
import sys from PySide6.QtWidgets import QApplication, QProgressBar, QWidget, QPushButton, QVBoxLayout from PySide6.QtCore import QThread, Signal import time class Thread(QThread): change_value = Signal() def run(self): self.change_value.emit() class Form(QWidget): def __init__(self): QWidget.__init__(self) self.pgsb = QProgressBar() self.pb = QPushButton("Pause") self.th = Thread() self.init_widget() self.th.change_value.connect(self.update_progressbar) self.th.start() def init_widget(self): layout = QVBoxLayout() self.setLayout(layout) layout.addWidget(self.pgsb) layout.addWidget(self.pb) def update_progressbar(self): cnt = 0 while True: if cnt == 100: cnt = 0 cnt += 1 self.pgsb.setValue(cnt) time.sleep(0.5) if __name__ == "__main__": app = QApplication(sys.argv) form = Form() form.show() sys.exit(app.exec())
这段代码无法正常工作,但下方代码却能正常运行:
import sys from PySide6.QtWidgets import QApplication, QProgressBar, QWidget, QPushButton, QVBoxLayout from PySide6.QtCore import QThread, Signal import time class Thread(QThread): change_value = Signal(int) def run(self): cnt = 0 while True: if cnt == 100: cnt = 0 cnt += 1 self.change_value.emit(cnt) time.sleep(0.5) class Form(QWidget): def __init__(self): QWidget.__init__(self) self.pgsb = QProgressBar() self.th = Thread() self.init_widget() self.th.change_value.connect(self.update_progressbar) self.th.start() def init_widget(self): layout = QVBoxLayout() self.setLayout(layout) layout.addWidget(self.pgsb) def update_progressbar(self, value): self.pgsb.setValue(value) if __name__ == "__main__": app = QApplication(sys.argv) form = Form() form.show() sys.exit(app.exec())
两段代码的核心差异解析
线程的作用范围不同
- 第一段代码中,子线程
Thread的run方法只发射一次信号就结束了,耗时的死循环和time.sleep(0.5)都放在了主线程的槽函数update_progressbar里。Qt的信号槽默认会把跨线程的槽函数调度到主线程执行,等于所有耗时操作都卡死了主线程,UI自然无法响应。 - 第二段代码中,子线程
Thread自己承担了耗时的循环和休眠操作,这部分逻辑完全在子线程中运行,不会影响主线程的UI渲染。
- 第一段代码中,子线程
信号的职责不同
- 第一段的信号只是触发了主线程的耗时任务,完全没发挥子线程的作用。
- 第二段的信号只负责传递计算好的进度值,主线程的槽函数只做轻量的UI更新操作,符合Qt"子线程处理耗时任务,主线程处理UI"的设计原则。
UI操作的线程规则
Qt规定所有UI控件的操作必须在主线程执行,第二段代码中更新进度条的操作放在主线程槽函数是正确的;而第一段代码错误地把耗时逻辑放在了主线程,既违反了线程使用规范,又导致UI阻塞。
内容的提问来源于stack exchange,提问作者kyung jin
相关产品推荐
相关产品推荐

