当前位置: 首页 > news >正文

【PyQt】QThread快速创建多线程任务

pyqt通过QThread快速创建多线程任务

在 PyQt5 中使用多线程时,需要注意 GUI 线程(主线程) 和 工作线程 的分离。PyQt5 的主线程负责处理 GUI 事件,如果在主线程中执行耗时任务,会导致界面卡顿甚至无响应。因此,耗时任务应该放在工作线程中执行。

PyQt5 提供了 QThread 来实现多线程编程

1. 使用 QThread 的基本步骤

1.1创建一个继承自 QThread 的类
1.2重写 run() 方法,在 run() 中执行耗时任务
1.3在主线程中创建并启动工作线程。
1.4使用信号(pyqtSignal)实现线程间通信

2. 示例代码

以下是一个简单的示例,展示如何使用 QThread 在后台执行耗时任务,同时更新 GUI。

import sys
import time
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QLabel# 自定义工作线程
class WorkerThread(QThread):# 定义一个信号,用于更新 GUIupdate_signal = pyqtSignal(str)def run(self):for i in range(1, 6):time.sleep(1)  # 模拟耗时任务self.update_signal.emit(f"Working... {i}/5")  # 发送信号self.update_signal.emit("Task completed!")  # 任务完成# 主窗口类
class MainWindow(QWidget):def __init__(self):super().__init__()self.init_ui()def init_ui(self):self.setWindowTitle("PyQt5 多线程示例")self.setGeometry(100, 100, 300, 150)# 创建布局和控件layout = QVBoxLayout()self.label = QLabel("点击按钮开始任务", self)self.button = QPushButton("开始任务", self)layout.addWidget(self.label)layout.addWidget(self.button)self.setLayout(layout)# 绑定按钮点击事件self.button.clicked.connect(self.start_task)def start_task(self):self.label.setText("任务开始...")self.button.setEnabled(False)  # 禁用按钮,防止重复点击# 创建工作线程self.worker = WorkerThread()self.worker.update_signal.connect(self.update_label)  # 连接信号到槽函数self.worker.finished.connect(self.task_finished)  # 任务完成时触发self.worker.start()  # 启动线程def update_label(self, message):self.label.setText(message)  # 更新标签内容def task_finished(self):self.button.setEnabled(True)  # 启用按钮# 运行程序
if __name__ == "__main__":app = QApplication(sys.argv)window = MainWindow()window.show()sys.exit(app.exec_())

3. 代码说明

WorkerThread:
class WorkerThread(QThread):
# 定义一个信号,用于更新 GUIupdate_signal = pyqtSignal(str)def run(self):for i in range(1, 6):time.sleep(1)  # 模拟耗时任务self.update_signal.emit(f"Working... {i}/5")  # 发送信号self.update_signal.emit("Task completed!")  # 任务完成
  • 继承自 QThread,重写 run() 方法。

  • 在 run() 中执行耗时任务,并通过 pyqtSignal 发送信号更新 GUI

  • .emit() 是用于手动发射信号的方法。通常在自定义信号时使用,类似于clicked

MainWindow:
# 主窗口类
class MainWindow(QWidget):def __init__(self):super().__init__()self.init_ui()def init_ui(self):self.setWindowTitle("PyQt5 多线程示例")self.setGeometry(100, 100, 300, 150)# 创建布局和控件layout = QVBoxLayout()self.label = QLabel("点击按钮开始任务", self)self.button = QPushButton("开始任务", self)layout.addWidget(self.label)layout.addWidget(self.button)self.setLayout(layout)# 绑定按钮点击事件self.button.clicked.connect(self.start_task)
  • 主窗口类,包含一个标签和一个按钮。

  • 点击按钮后,启动工作线程并禁用按钮,防止重复点击。

  • 通过信号和槽机制更新标签内容。

信号与槽:

start_task是按钮点击之后的槽函数

def start_task(self):self.label.setText("任务开始...")self.button.setEnabled(False)  # 禁用按钮,防止重复点击# 创建工作线程self.worker = WorkerThread()self.worker.update_signal.connect(self.update_label)  # 连接信号到槽函数self.worker.finished.connect(self.task_finished)  # 任务完成时触发self.worker.start()  # 启动线程def update_label(self, message):self.label.setText(message)  # 更新标签内容def task_finished(self):self.button.setEnabled(True)  # 启用按钮
  • update_signal:用于从工作线程向主线程传递消息

  • finished:QThread 的内置信号,当 run() 方法执行完毕时触发。

4. 注意事项

线程安全:

不要在子线程中直接操作 GUI 元素(如更新标签、修改按钮状态等),必须通过信号和槽机制实现

PyQt5 的信号和槽机制是线程安全的。

避免阻塞主线程:

所有耗时任务都应放在工作线程中执行,确保主线程能够及时响应 GUI 事件。

线程生命周期:

线程启动后,run() 方法执行完毕时线程会自动结束

如果需要手动终止线程,可以调用 QThread 的 quit() 或 terminate() 方法(但不推荐强制终止线程)。

5. 更复杂的场景

如果需要处理更复杂的多线程任务(如线程池、任务队列等),可以使用 Python 的 concurrent.futures 模块或 QRunnable + QThreadPool 实现。

使用 QRunnable 和 QThreadPool 的示例
from PyQt5.QtCore import QRunnable, QThreadPool, pyqtSignal, QObjectclass Worker(QRunnable):def __init__(self):super().__init__()self.signals = WorkerSignals()def run(self):for i in range(1, 6):time.sleep(1)self.signals.update_signal.emit(f"Working... {i}/5")self.signals.update_signal.emit("Task completed!")class WorkerSignals(QObject):update_signal = pyqtSignal(str)# 在主窗口中使用
class MainWindow(QWidget):def __init__(self):super().__init__()self.init_ui()self.thread_pool = QThreadPool()  # 创建线程池def start_task(self):worker = Worker()worker.signals.update_signal.connect(self.update_label)self.thread_pool.start(worker)  # 将任务提交到线程池
线程池大小:

QThreadPool 默认会根据系统资源自动调整线程数量。

可以通过 QThreadPool.globalInstance().setMaxThreadCount() 设置最大线程数。

相关文章:

【PyQt】QThread快速创建多线程任务

pyqt通过QThread快速创建多线程任务 在 PyQt5 中使用多线程时,需要注意 GUI 线程(主线程) 和 工作线程 的分离。PyQt5 的主线程负责处理 GUI 事件,如果在主线程中执行耗时任务,会导致界面卡顿甚至无响应。因此&#x…...

智能码二维码的成本效益分析

以下是智能码二维码的成本效益分析: 成本方面 硬件成本 标签成本:二维码标签本身价格低廉,即使进行大规模应用,成本也相对较低。如在智能仓储中,塑料托盘加二维码方案的标签成本几乎可以忽略不计4。扫描设备成本&…...

企业财务管理系统的需求设计和实现

该作者的原创文章目录: 生产制造执行MES系统的需求设计和实现 企业后勤管理系统的需求设计和实现 行政办公管理系统的需求设计和实现 人力资源管理HR系统的需求设计和实现 企业财务管理系统的需求设计和实现 董事会办公管理系统的需求设计和实现 公司组织架构…...

Springboot集成Swagger和Springdoc详解

Springboot2.x集成Swagger21. Springboot匹配版本2.7.0~2.7.18(其它版本需要自己去调试匹配)2. 首先导入Swagger2匹配的依赖项3. 导入依赖后创建配置文件SwaggerConfig4. Swagger集成完后,接下来接口的配置Springboot3.x集成Springdoc1. Springboot3.x依赖Springdoc配置2. 在…...

类和对象(4)——多态:方法重写与动态绑定、向上转型和向下转型、多态的实现条件

目录 1. 向上转型和向下转型 1.1 向上转型 1.2 向下转型 1.3 instanceof关键字 2. 重写(overidde) 2.1 方法重写的规则 2.1.1 基础规则 2.1.2 深层规则 2.2 三种不能重写的方法 final修饰 private修饰 static修饰 3. 动态绑定 3.1 动态绑…...

ui-automator定位官网文档下载及使用

一、ui-automator定位官网文档简介及下载 AndroidUiAutomator:移动端特有的定位方式,uiautomator是java实现的,定位类型必须写成java类型 官方地址:https://developer.android.com/training/testing/ui-automator.html#ui-autom…...

董事会办公管理系统的需求设计和实现

该作者的原创文章目录: 生产制造执行MES系统的需求设计和实现 企业后勤管理系统的需求设计和实现 行政办公管理系统的需求设计和实现 人力资源管理HR系统的需求设计和实现 企业财务管理系统的需求设计和实现 董事会办公管理系统的需求设计和实现 公司组织架构…...

ESP32和STM32在处理中断方面的区别

为了通俗地讲解ESP32和STM32在处理中断方面的区别,我们可以把它们想象成两个不同的“智能管家”系统,各自负责管理一个家庭(即嵌入式项目)的各种任务。我们将重点放在如何处理突发事件(即中断)上。 ESP32 …...

零售业革命:改变行业的顶级物联网用例

mpro5 产品负责人Ruby Whipp表示,技术进步持续重塑零售业,其中物联网(IoT)正引领这一变革潮流。 研究表明,零售商们正在采用物联网解决方案,以提升运营效率并改善顾客体验。这些技术能够监控运营的各个方面…...

字符串算法笔记

字符串笔记 说到字符串,首先我们要注意的就是字符串的输入以及输出,因为字符串的输入格式以及要求也分为很多种,我们就来说几个比较常见的格式 g e t s gets gets 我们先来说这个函数的含义...

在Ubuntu上用Llama Factory命令行微调Qwen2.5的简单过程

半年多之前写过一个教程:在Windows上用Llama Factory微调Llama 3的基本操作_llama-factory windows-CSDN博客 如果用命令行做的话,前面的步骤可以参考上面这个博客。安装好环境后, 用自我认知数据集微调Lora模块:data/identity.j…...

ThinkPhp伪静态设置后,访问静态资源也提示找不到Controller

ThinkPhp没有配置伪静态时,除了默认的IndexController能访问,其他路由Controller都访问不到,提示404错误。配置了伪静态后就解决了这个问题。 但是当我的ThinkPhp后台项目中有静态资源放在public目录(或子目录)中需要…...

JavaScript赋能智能网页设计

构建AI驱动的实时风格迁移系统 案例概述 本案例将实现一个基于深度学习的实时图像风格迁移系统,通过浏览器端神经网络推理实现以下高级特性: WebAssembly加速的ONNX模型推理 WebGL Shader实现的风格混合算法 WebRTC实时视频流处理 基于Web Workers的…...

基于STM32的阿里云智能农业大棚

目录 前言: 项目效果演示: 一、简介 二、硬件需求准备 三、硬件框图 四、CubeMX配置 4.1、按键、蜂鸣器GPIO口配置 4.2、ADC输入配置 4.3、IIC——驱动OLED 4.4、DHT11温湿度读取 4.5、PWM配置——光照灯、水泵、风扇 4.6、串口——esp8266模…...

80,【4】BUUCTF WEB [SUCTF 2018]MultiSQL

53,【3】BUUCTF WEB october 2019 Twice SQLinjection-CSDN博客 上面这个链接是我第一次接触二次注入 这道题也涉及了 对二次注入不熟悉的可以看看 BUUCTF出了点问题,打不开,以下面这两篇wp作为学习对象 [SUCTF 2018]MultiSQL-CSDN博客 …...

深入探索imi框架:PHP Swoole的高性能协程应用实践

摘要 本文将介绍 imi 框架,这是一个基于 PHP Swoole 的高性能协程应用开发框架。imi 支持 HttpApi、WebSocket、TCP 和 UDP 等多种服务类型,利用 Swoole 的优化技术,使得在处理请求时响应速度远超传统的 php-fpm 方式。通过丰富的代码示例&a…...

【算法篇·更新中】C++秒入门(附练习用题目)

一.二分 1.二分查找 我们来看这样一道题&#xff1a; 有一个保证有序的数组a&#xff0c;它的长度为n。现在我们需要知道这个序列是否含有x。 数据范围&#xff1a;保证n<1e9 我们看到这道题之后&#xff0c;第一时间想到的就是暴力枚举了&#xff0c;可是我们发现直接枚举…...

对神经网络基础的理解

目录 一、《python神经网络编程》 二、一些粗浅的认识 1&#xff09; 神经网络也是一种拟合 2&#xff09;神经网络不是真的大脑 3&#xff09;网络构建需要反复迭代 三、数字图像识别的实现思路 1&#xff09;建立一个神经网络类 2&#xff09;权重更新的具体实现 3&am…...

存储基础 -- SCSI命令格式与使用场景

SCSI命令格式与使用场景 1. SCSI命令描述符块&#xff08;CDB&#xff09; 1.1 CDB基本概念 SCSI命令通过**命令描述符块&#xff08;CDB, Command Descriptor Block&#xff09;**表示。 CDB长度&#xff1a;SCSI命令根据使用场景有不同长度的CDB&#xff0c;常见的有6字节…...

从崩溃难题看 C 标准库与 Rust:线程安全问题引发的深度思考

在软件开发的世界里&#xff0c;每一次技术的变革和尝试都伴随着未知的挑战。EdgeDB 团队在将部分网络 I/O 代码从 Python 迁移到 Rust 的过程中&#xff0c;就遭遇了一场棘手的问题&#xff0c;这个问题不仅暴露了 C 标准库的线程安全隐患&#xff0c;也让我们对 Rust 的 “安…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂

蛋白质结合剂&#xff08;如抗体、抑制肽&#xff09;在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上&#xff0c;高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术&#xff0c;但这类方法普遍面临资源消耗巨大、研发周期冗长…...

YSYX学习记录(八)

C语言&#xff0c;练习0&#xff1a; 先创建一个文件夹&#xff0c;我用的是物理机&#xff1a; 安装build-essential 练习1&#xff1a; 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件&#xff0c;随机修改或删除一部分&#xff0c;之后…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

第25节 Node.js 断言测试

Node.js的assert模块主要用于编写程序的单元测试时使用&#xff0c;通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试&#xff0c;通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...

【AI学习】三、AI算法中的向量

在人工智能&#xff08;AI&#xff09;算法中&#xff0c;向量&#xff08;Vector&#xff09;是一种将现实世界中的数据&#xff08;如图像、文本、音频等&#xff09;转化为计算机可处理的数值型特征表示的工具。它是连接人类认知&#xff08;如语义、视觉特征&#xff09;与…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...