python GUI库图形界面开发之PyQt5 UI主线程与耗时线

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程序,单线程模式可能是更为适用的。

后端开发标签