【python】pyqt中使用多线程处理耗时任务
在 PyQt 中使用多线程通常是为了避免界面冻结,特别是在执行耗时的任务时。PyQt 本身是基于 Qt 的,而 Qt 不允许在除主线程之外的线程中直接操作 GUI 元素。因此,任何涉及 GUI 更新的操作都应该在主线程中执行。
import sys
import threading
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QLabel
from PyQt5.QtCore import QThread, pyqtSignal
import time
# 定义一个线程类,继承自 QThread
class WorkerThread(QThread):
# 定义一个信号,用于在主线程中更新文本
result_ready = pyqtSignal(str)
def run(self):
"""线程执行的函数"""
# 模拟一个耗时的任务
time.sleep(5)
result = "任务完成"
# 发出信号,通知主线程
self.result_ready.emit(result)
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle('PyQt 多线程示例')
self.setGeometry(300, 300, 300, 200)
layout = QVBoxLayout()
self.label = QLabel('等待任务...')
layout.addWidget(self.label)
self.button = QPushButton('开始任务')
self.button.clicked.connect(self.start_task)
layout.addWidget(self.button)
self.setLayout(layout)
self.show()
def start_task(self):
# 创建线程实例
self.thread = WorkerThread()
# 连接线程的信号到槽函数
self.thread.result_ready.connect(self.on_result_ready)
# 启动线程
self.thread.start()
def on_result_ready(self, result):
# 在主线程中更新标签文本
self.label.setText(result)
# 线程完成后,可以确保线程被清理
self.thread.quit()
self.thread.wait()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())
传入一个函数进入线程中执行
import sys
import threading
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout
from PyQt5.QtCore import QThread, pyqtSignal
# 定义一个普通的 Python 函数
def task_function(data):
# 执行一些任务,这里只是简单地打印数据
print(f"线程中执行函数,数据为: {data}")
# 模拟耗时操作
threading.Event().wait(2) # 等待2秒
# 定义一个线程类,继承自 QThread
class WorkerThread(QThread):
# 定义一个信号,用于通知主线程任务完成
finished = pyqtSignal()
def __init__(self, function, data):
super().__init__()
# 将函数和数据作为属性保存
self.function = function
self.data = data
def run(self):
# 在线程中执行传入的函数
self.function(self.data)
# 发出信号通知任务完成
self.finished.emit()
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle('PyQt 多线程示例')
self.setGeometry(300, 300, 300, 200)
layout = QVBoxLayout()
self.button = QPushButton('开始任务')
self.button.clicked.connect(self.start_task)
layout.addWidget(self.button)
self.setLayout(layout)
self.show()
def start_task(self):
# 定义要在线程中执行的数据
data = "Hello from thread"
# 创建线程实例,并传递函数和数据
self.thread = WorkerThread(task_function, data)
# 连接线程的信号到槽函数(这里只是打印消息,实际中可以做更多处理)
self.thread.finished.connect(self.on_thread_finished)
# 启动线程
self.thread.start()
def on_thread_finished(self):
# 线程完成后执行的代码
print("线程任务完成")
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())