1. PyQt5概述
PyQt5是一个基于Python语言的GUI框架,为开发图形界面应用提供了丰富的工具库和组件,灵活性和可扩展性很高。在PyQt5中,常见的GUI组件包括QMainWindow、QWidget和QLabel等。
2. PyQt5主线程与耗时线程
PyQt5程序一般包括交互性部分和计算密集型部分。交互性部分指的是用户与程序的交互界面,而计算密集型部分指的是需要占用大量CPU资源的计算操作。在GUI程序中,由于涉及到用户交互,主线程无法长时间被耗时阻塞,因此我们需要将耗时的计算操作放入单独的线程中实现,以避免主线程被阻塞,导致界面假死。
2.1 多线程实现
在PyQt5中实现多线程的方式可以有两种,一种是继承QThread类,一种是使用QRunnable接口。下面我们将介绍这两种方式的实现方法。
2.1.1 继承QThread类
在此方式中,我们需要先创建一个继承自QThread的自定义类,并重写其中的run()方法,将耗时的计算操作写入run()方法中。当需要启动线程时,我们只需要实例化此自定义类,并使用start()方法即可启动线程。
from PyQt5.QtCore import QThread
class MyThread(QThread):
def __init__(self):
super().__init__()
def run(self):
# 耗时的计算操作
2.1.2 使用QRunnable接口
在此方式中,我们需要创建一个继承自QObject的自定义类,并实现其中的run()方法,将耗时的计算操作写入run()方法中。然后将此自定义类实例化为QRunnable对象,并加入到QThreadPool线程池中,使用线程池来执行计算操作。
from PyQt5.QtCore import QObject, QRunnable, QThreadPool
class MyRunnable(QObject, QRunnable):
def __init__(self):
super().__init__()
def run(self):
# 耗时的计算操作
# 实例化MyRunnable对象为QRunnable对象,并加入到线程池中
runnable = MyRunnable()
QThreadPool.globalInstance().start(runnable)
2.2 线程间的通信
在线程间进行数据的传输和通信也是GUI程序制作中必不可少的一部分。在PyQt5中,我们可以使用信号与槽机制实现线程间的数据交互与通信。当耗时线程执行完毕后,我们可以使用信号向主线程发送消息,从而实现主线程的更新操作。
from PyQt5.QtCore import QObject, QRunnable, QThreadPool, pyqtSignal
class MyRunnable(QObject, QRunnable):
# 指定返回值为整型的信号
finished = pyqtSignal(int)
def __init__(self):
super().__init__()
def run(self):
# 耗时的计算操作
result = 1 + 2
self.finished.emit(result)
# 实例化MyRunnable对象为QRunnable对象,并加入到线程池中
runnable = MyRunnable()
# 连接finished信号与槽函数
runnable.finished.connect(self.update_ui)
QThreadPool.globalInstance().start(runnable)
def update_ui(self, result):
# 主线程的更新操作
3. 实战案例
下面以一个简单的PyQt5程序为例,来演示如何使用多线程实现较为耗时的计算操作,并在计算完成后更新主线程的界面。
3.1 界面设计
我们在界面上设置两个文本框和一个按钮,分别用于输入数字、显示结果和启动程序,如下图所示。
![GUI界面设计](https://pic.imgdb.cn/item/617607c63ffa7d37b37337fc.jpg)
3.2 代码实现
首先,我们在主线程中实例化文本框、按钮及其对应的槽函数,并将耗时计算操作放入子线程中执行。计算完成后,用信号将结果传回主线程,并更新结果文本框中的值。
from PyQt5.QtCore import QObject, QRunnable, QThreadPool, pyqtSignal
from PyQt5.QtWidgets import QMainWindow, QApplication
from PyQt5.uic import loadUi
class MyRunnable(QObject, QRunnable):
# 指定返回值为整型的信号
finished = pyqtSignal(int)
def __init__(self):
super().__init__()
def run(self):
# 耗时的计算操作
result = 1 + 2
self.finished.emit(result)
class MyWindow(QMainWindow):
def __init__(self):
super().__init__()
# 加载UI界面
loadUi("mywindow.ui", self)
# 处理按钮事件
self.pushButton_start.clicked.connect(self.do_work)
def do_work(self):
# 实例化耗时线程
runnable = MyRunnable()
# 连接finished信号与槽函数
runnable.finished.connect(self.update_ui)
# 启动耗时线程
QThreadPool.globalInstance().start(runnable)
def update_ui(self, result):
# 更新结果文本框中的值
self.lineEdit_result.setText(str(result))
if __name__ == "__main__":
app = QApplication([])
win = MyWindow()
win.show()
app.exec_()
使用以上代码来运行我们的PyQt5程序就可以实现在线程中执行耗时操作,在计算完成后更新主线程的界面。
本文介绍了PyQt5中多线程和信号槽机制的基本使用方法,并给出了一个实例代码。在实际应用中,我们在进行计算操作时也要注意,多线程并不总是越多越好,对于负载较小的GUI程序,单线程模式可能是更为适用的。