PyQt5 QThread 的多个方面详解

一、QThread 的背景和概念

Python语言下的GUI编程常用的库是PyQt5,而其中的QThread则是经常用到的一个类。QThread是封装了线程(thread)的Qt库中的类。线程是我们常说的一个程序中的独立流程,它是一个包含指令序列的执行单元,是一个进程内部的一个相对独立的、可调度的执行单元。有了线程可以实现多任务并行执行,提高程序的执行效率。但实现多线程程序不是一件容易的事情,有许多难以解决的问题,而PyQt5中的QThread类就提供了一个相对较简单的线程实现方式。

在使用QThread之前,需要了解一些与多线程有关的概念,包括:sleep、信号(Signal)和槽(Slot)等概念。sleep是使线程进入睡眠状态,暂停执行一段时间后重新执行。信号和槽是在不同线程间通讯的机制,其中信号是在发生某个特定事件时发送的一种消息,而槽则是由线程处理该消息并执行相应的动作。


import time, threading

def func():
    for i in range(5):
        time.sleep(1)
        print('func executed')

t = threading.Thread(target=func)
t.start()

二、QThread 的基本用法

QThread类的应用可以分为两步:第一步是创建QThread对象,第二步是在QThread对象中创建一个自定义的类继承QThread,并重写其run方法。run方法就是我们想要在线程中执行的代码。在自定义类中可以使用信号和槽机制与主线程(或其他线程)交互。

下面是一个简单的QThread使用示例,先看代码:


import sys
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtWidgets import QApplication, QWidget, QLabel


class Worker(QThread):
    signal_output = pyqtSignal(str)

    def __init__(self, parent=None):
        super(Worker, self).__init__(parent)

    def run(self):
        for i in range(3):
            self.signal_output.emit(f"Worker thread output {i}")
            self.sleep(1)

class MainWidget(QWidget):
    def __init__(self, parent=None):
        super(MainWidget, self).__init__(parent)
        self.label = QLabel(self)
        self.worker = Worker(self)

        self.worker.signal_output.connect(self.handle_output)
        self.worker.start()

    def handle_output(self, msg):
        self.label.setText(msg)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = MainWidget()
    w.show()
    sys.exit(app.exec_())

这段代码的功能是创建一个主线程的QWidget窗口,其中包含一个QLabel标签。在程序运行时,会启动一个子线程(即Worker类),每隔一秒发送一个信号并emit(激活)一个自定义的信号signal_output,发送内容是字符串“Worker thread output i”,其中 i 从 0 开始每次加 1。而界面则会在接收到信号后把字符串显示到QLabel标签上。

三、QThread 的高级应用

除了基本的使用外,QThread还有一些高级用法,例如如何优雅地停止线程、如何在线程中使用QTimer、QThreadPool等等。

下面是一个使用QTimer的例子,在子线程中每隔1秒将数据+1并输出,同时还有一个按下按钮可以暂停线程:


import sys
from PyQt5.QtCore import QThread, QTimer, pyqtSlot, pyqtSignal
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout, QPushButton


class Worker(QThread):
    signal_output = pyqtSignal(int)

    def __init__(self, parent=None):
        super(Worker, self).__init__(parent)
        self.timer = QTimer(self)
        self.timer.timeout.connect(self._process_data)
        self.iteration = 0
        self.is_running = True

    def _process_data(self):
        self.iteration += 1
        self.signal_output.emit(self.iteration)

    def run(self):
        self.timer.start(1000)

        while self.is_running:
            self.sleep(1)

        self.timer.stop()

    def stop(self):
        self.is_running = False


class MainWidget(QWidget):
    def __init__(self, parent=None):
        super(MainWidget, self).__init__(parent)
        self.label = QLabel(self)
        self.button = QPushButton("Stop", self)

        self.layout = QVBoxLayout(self)
        self.layout.addWidget(self.label)
        self.layout.addWidget(self.button)

        self.worker = Worker(self)

        self.worker.signal_output.connect(self.handle_output)
        self.button.clicked.connect(self.worker.stop)

        self.worker.start()

    @pyqtSlot(int)
    def handle_output(self, value):
        self.label.setText(f"Worker thread output {value}")


if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = MainWidget()
    w.show()
    sys.exit(app.exec_())

这段代码采用QTimer作为定时器,每隔1秒触发一次_process_data函数,将iteration的数值加1,并将数值emit到自定义的信号signal_output中。同时,在外部有一个按钮可以调用worker的stop方法,以便优雅地停止线程。

四、总结

QThread是PyQt5库中常用的多线程编程类,可以轻松地实现多线程效果。在应用QThread时需要注意一些线程概念和信号槽机制,并且如果需要更高级的应用(例如使用QTimer、QThreadPool等)则需要对QThread类更加深入地了解。

原创文章,作者:JHLE,如若转载,请注明出处:https://www.506064.com/n/141651.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
JHLEJHLE
上一篇 2024-10-08 17:53
下一篇 2024-10-08 17:53

相关推荐

  • 为什么Python不能编译?——从多个方面浅析原因和解决方法

    Python作为很多开发人员、数据科学家和计算机学习者的首选编程语言之一,受到了广泛关注和应用。但与之伴随的问题之一是Python不能编译,这给基于编译的开发和部署方式带来不少麻烦…

    编程 2025-04-29
  • Java判断字符串是否存在多个

    本文将从以下几个方面详细阐述如何使用Java判断一个字符串中是否存在多个指定字符: 一、字符串遍历 字符串是Java编程中非常重要的一种数据类型。要判断字符串中是否存在多个指定字符…

    编程 2025-04-29
  • Python合并多个相同表头文件

    对于需要合并多个相同表头文件的情况,我们可以使用Python来实现快速的合并。 一、读取CSV文件 使用Python中的csv库读取CSV文件。 import csv with o…

    编程 2025-04-29
  • 从多个方面用法介绍yes,but let me review and configure level of access

    yes,but let me review and configure level of access是指在授权过程中,需要进行确认和配置级别控制的全能编程开发工程师。 一、授权确…

    编程 2025-04-29
  • 从多个方面zmjui

    zmjui是一个轻量级的前端UI框架,它实现了丰富的UI组件和实用的JS插件,让前端开发更加快速和高效。本文将从多个方面对zmjui做详细阐述,帮助读者深入了解zmjui,以便更好…

    编程 2025-04-28
  • 学Python用什么编辑器?——从多个方面评估各种Python编辑器

    选择一个适合自己的 Python 编辑器并不容易。除了我们开发的应用程序类型、我们面临的软件架构以及我们的编码技能之外,选择编辑器可能也是我们编写代码时最重要的决定之一。随着许多不…

    编程 2025-04-28
  • 使用easypoi创建多个动态表头

    本文将详细介绍如何使用easypoi创建多个动态表头,让表格更加灵活和具有可读性。 一、创建单个动态表头 easypoi是一个基于POI操作Excel的Java框架,支持通过注解的…

    编程 2025-04-28
  • 创建列表的多个方面

    本文将从多个方面对创建列表进行详细阐述。 一、列表基本概念 列表是一种数据结构,其中元素以线性方式组织,并且具有特殊的序列位置。该位置可以通过索引或一些其他方式进行访问。在编程中,…

    编程 2025-04-28
  • Python多个sheet表合并用法介绍

    本文将从多个方面对Python多个sheet表合并进行详细的阐述。 一、xlrd与xlwt模块的基础知识 xlrd与xlwt是Python中处理Excel文件的重要模块。xlrd模…

    编程 2025-04-27
  • 从多个角度用法介绍lower down

    lower down是一个常用于编程开发中的操作。它可以对某个值或变量进行降低精度的处理,非常适合于一些需要精度不高但速度快的场景。那么,在本文中,我们将从多个角度解析lower …

    编程 2025-04-27

发表回复

登录后才能评论