PyQt4线程正确实现:线程运行进度条且支持窗口拖拽
实现QThread中运行QProgressBar并支持主窗口拖拽移动
嘿,我明白你的需求啦——要让进度条在后台线程跑,同时主窗口还能随意拖拽移动,不会因为进度更新卡死UI对吧?这事儿得靠Qt的信号槽机制来解决,因为直接在主线程跑耗时任务会阻塞UI事件循环,导致窗口拖不动。下面是完整的实现代码,我给你标注了关键要点:
完整代码实现
import sys from PyQt4.QtGui import QApplication, QMainWindow, QPushButton, QProgressBar, QVBoxLayout, QWidget from PyQt4.QtCore import QThread, SIGNAL, Qt # 自定义进度线程类,负责在后台计算进度并发送信号 class ProgressThread(QThread): def __init__(self, parent=None): super(ProgressThread, self).__init__(parent) self._is_running = True def run(self): # 模拟耗时的进度任务,比如文件下载、数据处理 for progress in range(0, 101, 5): if not self._is_running: break # 发送进度信号给主线程,更新UI self.emit(SIGNAL('progress(int)'), progress) # 模拟任务耗时 self.msleep(200) def stop(self): self._is_running = False self.wait() class App(QMainWindow): def __init__(self): super(App, self).__init__() self.setGeometry(500, 300, 820, 350) self.setWindowTitle("Program") self.initUI() # 初始化进度线程 self.progress_thread = ProgressThread() def initUI(self): # 主窗口中心部件和布局 central_widget = QWidget() self.setCentralWidget(central_widget) layout = QVBoxLayout(central_widget) # 创建进度条 self.progress_bar = QProgressBar(self) self.progress_bar.setAlignment(Qt.AlignCenter) layout.addWidget(self.progress_bar) # 创建启动按钮 self.start_btn = QPushButton("启动进度条", self) self.start_btn.clicked.connect(self.start_progress) layout.addWidget(self.start_btn) # 创建停止按钮 self.stop_btn = QPushButton("停止进度条", self) self.stop_btn.clicked.connect(self.stop_progress) layout.addWidget(self.stop_btn) def start_progress(self): # 连接线程的进度信号到进度条的更新槽 self.connect(self.progress_thread, SIGNAL('progress(int)'), self.progress_bar.setValue) # 启动线程(非阻塞,主线程继续处理UI事件) self.progress_thread.start() self.start_btn.setEnabled(False) self.stop_btn.setEnabled(True) def stop_progress(self): self.progress_thread.stop() self.start_btn.setEnabled(True) self.stop_btn.setEnabled(False) def closeEvent(self, event): # 窗口关闭时停止线程,避免资源泄漏 self.progress_thread.stop() event.accept() if __name__ == '__main__': app = QApplication(sys.argv) ex = App() ex.show() sys.exit(app.exec_())
关键要点说明
- 线程与UI分离:进度计算逻辑完全放在
ProgressThread子线程中,主线程只负责接收信号更新UI,这样主线程的事件循环不会被阻塞,窗口拖拽、按钮点击等操作都能正常响应 - 信号槽通信:子线程不能直接修改UI元素,必须通过
emit发送信号,主线程通过connect绑定信号到进度条的setValue方法,这是Qt线程安全的核心要求 - 线程启停控制:添加了
stop方法和closeEvent处理,确保窗口关闭时线程能正常终止,避免内存泄漏 - 非阻塞启动:用
start()启动线程,而不是wait(),wait()会阻塞主线程,导致窗口卡死
这样运行代码后,点击启动按钮,进度条会慢慢更新,同时你可以随意拖拽主窗口,完全不会卡顿~
内容的提问来源于stack exchange,提问作者Artur Müller Romanov
相关产品推荐
相关产品推荐

