PyQt中的多线程使用方法(以PySide6为例)

2023-11-14

在Qt中,开启多线程的方法有多种,总体分成QThread、QObject、QRunnable、QtConcurrent三大类方法。

而放到PyQt和PySide具体的使用中,使用方法可以说十分类似。

一、继承QThread类及run方法。

此方法可以说是Qt线程的基础,主要方法是重写一个类, 继承QThread类,然后重写run方法。

例如:

# !/usr/bin python3
# -*- encoding=utf-8 -*-
# Description : 
# Author  : 
# @Email : 
# @File : 01_thread.py
# @Time : 2023-06-27 15:37:08
# @Project : qt

from PySide6.QtCore import QThread, Signal
from PySide6.QtWidgets import QWidget, QApplication, QPushButton


class Work(QThread):
    result = Signal()

    def __init__(self):
        QThread.__init__(self)

    def run(self) -> None:
        for i in range(0, 10):
            print('i = {}'.format(i))
            self.usleep(1000000)
        self.result.emit()


class Widget(QWidget):

    def __init__(self):
        QWidget.__init__(self)
        self._work = Work()
        self._work.result.connect(self._result)
        self._widget()

    def _widget(self):
        _btn = QPushButton('确定')
        _btn.setParent(self)
        _btn.clicked.connect(self._run)

    def _run(self):
        self._work.start()

    def _result(self):
        print('线程结束')


if __name__ == '__main__':
    app = QApplication()

    window = Widget()
    window.show()

    app.exec()

此方法的特点:

1、优点:可以通过信号槽与外界进行通信。
2、缺点:
1)每次新建一个线程都需要继承QThread,实现一个新类,使用不太方便。
2)要自己进行资源管理,线程释放和删除。并且频繁的创建和释放会带来比较大的内存开销。
3、适用场景:QThread适用于那些常驻内存的任务。

二、使用QObject类的moveToThread方法,调用QThread执行线程

创建一个继承QObject的类(如Work类),然后new一个Qthread,并把创建的Work类moveToThread到创建好的子线程中,然后start方法启动子线程,这样就实现了一个子线程。主线程通过发送信号,调用Work中的方法,从而实现在子线程中的计算。

# !/usr/bin python3
# -*- encoding=utf-8 -*-
# Description : 
# Author  : 
# @Email : 
# @File : 02_object.py
# @Time : 2023-06-27 16:00:40
# @Project : qt

from PySide6.QtCore import QThread, Signal, QObject
from PySide6.QtWidgets import QWidget, QApplication, QPushButton


class Work(QObject):
    result = Signal()
    is_run = False

    def __init__(self):
        QObject.__init__(self)

    def run(self) -> None:
        for i in range(0, 10):
            print('i = {}'.format(i))
            QThread.usleep(1000000)
        self.result.emit()

    def start(self):
        self.is_run = True

    def stop(self):
        self.is_run = False


class Widget(QWidget):

    def __init__(self):
        QWidget.__init__(self)
        self._widget()

    def _widget(self):
        _btn = QPushButton('确定')
        _btn.setParent(self)
        _btn.clicked.connect(self._run)

    def _run(self):
        _work = Work()
        _thread = QThread()
        _work.result.connect(self._result)
        _work.moveToThread(_thread)

    def _result(self):
        print('线程结束')


if __name__ == '__main__':
    app = QApplication()

    window = Widget()
    window.show()

    app.exec()

此方法的特点:

moveToThread对比传统子类化Qthread更灵活,仅需要把你想要执行的代码放到槽,moveToThread这个object到线程,然后拿一个信号连接到这个槽就可以让这个槽函数在线程里执行。可以说,moveToThread给我们编写代码提供了新的思路,当然不是说子类化qthread不好,只是你应该知道还有这种方式去调用线程。

轻量级的函数可以用moveToThread,多个短小精悍能返回快速的线程函数适用 ,无需创建独立线程类,例如你有20个小函数要在线程内做, 全部扔给一个QThread。而我觉得moveToThread和子类化QThread的区别不大,更可能是使用习惯引导。又或者你一开始没使用线程,但是后边发觉这些代码还是放线程比较好,如果用子类化QThread的方法重新设计代码,将会有可能让你把这一段推到重来,这个时候,moveToThread的好处就来了,你可以把这段代码的从属着moveToThread,把代码移到槽函数,用信号触发它就行了。其它的话moveToThread它的效果和子类化QThread的效果是一样的,槽就相当于你的run()函数,你往run()里塞什么代码,就可以往槽里塞什么代码,子类化QThread的线程只可以有一个入口就是run(),而moveToThread就有很多触发的入口。

三、使用QRunnable类

Qrunnable是所有可执行对象的基类。我们可以继承Qrunnable,并重写虚函数void QRunnable。run () 。

我们可以用QThreadPool让我们的一个QRunnable对象在另外的线程中运行,如果autoDelete()返回true(默认),那么QThreadPool将会在run()运行结束后自动删除Qrunnable对象。可以调用void QRunnable::setAutoDelete ( bool autoDelete )更改auto-deletion标记。

需要注意的是,必须在调用QThreadPool::start()之前设置,在调用QThreadPool::start()之后设置的结果是未定义的。

一、实现方法:

1、继承QRunnable。和QThread使用一样, 首先需要将你的线程类继承于QRunnable。

2、重写run函数。还是和QThread一样,需要重写run函数,run是一个纯虚函数,必须重写。

3、使用QThreadPool启动线程

代码示例:

# !/usr/bin python3
# -*- encoding=utf-8 -*-
# Description : 
# Author  : 
# @Email : 
# @File : 03_runable.py
# @Time : 2023-06-27 16:07:54
# @Project : qt


from PySide6.QtCore import QThread, Signal, QObject, QRunnable, QThreadPool
from PySide6.QtWidgets import QWidget, QApplication, QPushButton


class Runnable(QRunnable):

    def __init__(self):
        QRunnable.__init__(self)

    def run(self):
        for i in range(0, 10):
            print('i = {}'.format(i))
            QThread.usleep(1000000)


class Widget(QWidget):

    def __init__(self):
        QWidget.__init__(self)
        self._widget()

    def _widget(self):
        _btn = QPushButton('确定')
        _btn.setParent(self)
        _btn.clicked.connect(self._run)

    def _run(self):
        _run_able = Runnable()
        _run_able.setAutoDelete(True)  # Auto-deletion is enabled by default
        _pool = QThreadPool.globalInstance()
        _pool.start(_run_able)
        # _pool.waitForDone()  # 会阻塞UI

        # 可同时启动多个线程
        # QRunnable 不是QObject的子类 不能使用Signal, 不能使用信号槽与外界通信。



if __name__ == '__main__':
    app = QApplication()

    window = Widget()
    window.show()

    app.exec()

二、此方法的特点:

优点:无需手动释放资源,QThreadPool启动线程执行完成后会自动释放。
缺点:不能使用信号槽与外界通信。
适用场景:QRunnable适用于线程任务量比较大,需要频繁创建线程。QRunnable能有效减少内存开销。

四、使用QRunnable类中的静态方法create创建新线程

原理还是使用了QRunnable类来调用和开启新线程,但因为QRunnable类提供了一个静态方法->create方法, 所以可以实现在不写新类的情况下,直接开启和运行新线程。

代码示例:

# !/usr/bin python3
# -*- encoding=utf-8 -*-
# Description : 
# Author  : 
# @Email : 
# @File : 04_runable.py
# @Time : 2023-06-27 16:24:47
# @Project : qt

from PySide6.QtCore import QThread, QRunnable, QThreadPool
from PySide6.QtWidgets import QWidget, QApplication, QPushButton


class Widget(QWidget):

    def __init__(self):
        QWidget.__init__(self)
        self._widget()

    def _widget(self):
        _btn = QPushButton('确定')
        _btn.setParent(self)
        _btn.clicked.connect(self._run)

    def _run(self):
        _run_able = QRunnable.create(self._runnable)
        _run_able.setAutoDelete(True)  # Auto-deletion is enabled by default
        _pool = QThreadPool.globalInstance()
        _pool.start(_run_able)
        # _pool.waitForDone()  # 会阻塞UI


    def _runnable(self) -> None:
        for i in range(0, 10):
            print('i = {}'.format(i))
            QThread.usleep(500000)



if __name__ == '__main__':
    app = QApplication()

    window = Widget()
    window.show()

    app.exec()

五、QtConcurrent,并不能实现。

在Qt中,还有一种可以开启新线程的方法,QtConcurrent。

但遗憾的是,不管是在PyQt中,还是在PySide中,都没有方法可以调用此方式。

因为这个实现方法调用的是一个namespace, 而不是一个类,因此无法封装。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PyQt中的多线程使用方法(以PySide6为例) 的相关文章

随机推荐

  • 网络安全入门学习练手——CS伪装钓鱼网站

    文章目录 一 实验环境 二 使用工具和目标 三 开始复现 1 启动Cobalt Strike服务器端 打开Cobalt Strike客户端 2 设置监听器 3 网站克隆 4 在受害者端输入克隆网站对应的ip 5 测试 四 拓展 让钓鱼网址挂
  • 记录一次mac电脑安装git并在idea中使用的问题

    一 安装Git 下载地址 https sourceforge net projects git osx installer 点击下载最新版就可以了 下载速度很快的 下载完直接打开 默认安装即可 安装完成直接在命令行用root用户执行 git
  • L1-020 帅到没朋友(java)

    1 题目详情 当芸芸众生忙着在朋友圈中发照片的时候 总有一些人因为太帅而没有朋友 本题就要求你找出那些帅到没有朋友的人 输入格式 输入第一行给出一个正整数N 100 是已知朋友圈的个数 随后N行 每行首先给出一个正整数K 1000 为朋友圈
  • gcc make makefile 的基本介绍

    一 gcc 1 在window操作系统下 编译工具用集成开发环境 在Linux操作系统下没有很好的集成环境 用的编译器是gcc 2 程序的编译分为四个阶段 由 c到可执行程序 1 预编译 2 编译 3 汇编 4 链接 3 编译程序 1 一步
  • PTAMM阅读笔记之SLAM概述(五)

    1 同时定位与地图创建允许机器人在未知环境中 依靠自身所带的传感器递增式地创建环境地图 并同时给出机器人所在位置 2 移动机器人的定位有两种类型 全局定位 绝对定位 Global Absolute Localization 和位置跟踪 Po
  • Mybatis3快速上手(详细)

    因为编辑器不互通 所以可以直接打开有道云看 有道云链接 Mybatis的初入 创建Maven项目工程 因为Mybatis属于数据访问层的操作 我们需要引入相关依赖 mysql mysql connector java 8 0 29 org
  • HashMap实现原理及扩容机制详解

    文章目录 一 HashMap基础 二 红黑树基础 三 HashMap实现原理 1 Node和Node链 2 拉链法 3 关于Node数组 table 4 散列算法 5 HashMap和红黑树 6 关于TreeNode 转自 这篇更详细 ht
  • UNext:基于 MLP 的快速医学图像分割网络

    UNext 会议分析 摘要 贡献 方法 整体框架 1 Shifted MLP 2 Tokenized MLP Stage 实验 1 对比实验 2 消融实验 2 1 模块的消融实验 2 2 通道数的探索 可借鉴参考 会议分析 期刊 会议 名
  • 前端常见难点面试题

    1 跨域 同源策略 同源策略 同源策略是浏览器的一个安全功能 不同源的客户端脚本在没有明确授权的情况下 不能读写对方资源 同源 就是协议 域名和端口号相同 降域 document domain 同源策略认为域和子域属于不同的域 如 chil
  • 《代码走查》杂记

    代码走查 一 定义 1 代码走查 code walkthrough 是一个开发人员与架构师集中与讨论代码的过程 代码走查的目的交换有关代码是如何书写的思路 并建立一个对代码的标准集体阐述 在代码走查的过程中 开发人员都应该有机会向其他人来阐
  • OpenGL: 视图矩阵的推导

    OpenGL 视图矩阵的推导 2014年03月04日 11 08 45 阅读数 6525 把物体从世界坐标系转化到视点坐标系的矩阵称为视图矩阵 下面我们先看下opengl视图矩阵的推导过程 假设视点或camera的局部坐标系为UVN UVN
  • webpack中的代码分离

    Tip 本指南继续沿用 起步 中的示例代码 请确保你已熟悉这些指南中提供的示例以及输出管理章节 代码分离是 webpack 中最引人注目的特性之一 此特性能够把代码分离到不同的 bundle 中 然后可以按需加载或并行加载这些文件 代码分离
  • Python 九九乘法表的7种实现方式

    Python 九九乘法表的7种实现方式 九九乘法表是初学者学习编程的必要练手题目之一 因此各种语言都有对应的实现方式 而 Python 也不例外 在 Python 中 我们可以使用多种方式来生成一个简单的九九乘法表 实现方式一 双重循环 f
  • 远程debug java_远程Debug Java进程的方法

    远程debug的意思是启动一个Java进程 启动一个debugger进程 将两者连接起来 利用debugger来debug Java进程 事实上目前所有的IDE的debug功能都是通过远程debug方式来实现的 它们都利用了一个叫做JDPA
  • 【行人重识别】Unsupervised Salience Learning for Person Re-identification

    Abstract 人眼可以基于 一些较小的显着区域来识别人的身份 然而 当使用现有方法计算图像的相似度时 通常会隐藏这种有价值的显着信息 此外 许多现有的方法学习区别性特征并以监督的方式处理急剧的视点变化 并要求为不同的摄像机视图对标注新的
  • QSqlQueryModle使用过滤器来完成数据库数据筛选

    原型 void QSqlTableModel setFilter const QString filter 注意 如果模型已从数据库中填充数据 则模型将其与新滤波器重新选择 否则 将在调用下一次select 中应用过滤器 model的sel
  • 15.服务数据的定义与使用

    学习视频 https www bilibili com video BV1zt411G7Vn p 15 目标 服务数据的自定义 客户端发布显示个人信息的请求 服务端处理请求及反馈应答 一 自定义服务数据 1 定义srv文件 mkdir ca
  • Python 判断None的三种方法

    1 if x is None 2 if not x 3 if not x is None 在Python 中 None False 空字符串 空列表 空元组 其实都相当于False 如果x为空列表 y为None 如果你做x is None的
  • 社区版pycharm官网下载安装教程

    1 官网下载安装包 官网地址 https www jetbrains com pycharm 选择所需版本 2 安装 安装前确认已完成python软件安装 建议不要安装到C盘 路径不要出现中文 直接install 等待安装 3 配置 点击桌
  • PyQt中的多线程使用方法(以PySide6为例)

    在Qt中 开启多线程的方法有多种 总体分成QThread QObject QRunnable QtConcurrent三大类方法 而放到PyQt和PySide具体的使用中 使用方法可以说十分类似 一 继承QThread类及run方法 此方法