PySide6/PyQT多线程之 信号与槽 / (Signal Slot)的高效利用

news2024/10/6 1:36:41

在这里插入图片描述

前言

PySide6/PyQT信号槽是一种事件处理方式,允许程序中的对象发送和接收信号。

PySide6/PyQT 精进的过程中,一定躲不开 信号和槽 这座大山,这是一个比较有意思的知识点:

  • 初接触的看不懂,觉得复杂;
  • 看得懂的又觉得简单。

简单和难另说,将 PySide6/PyQT信号和槽 讲的清楚,这个才是重点。




其实也挺简单,分三步走:

  1. 定义信号Signal
  2. 定义槽Slot
  3. 将信号和槽连接:Signal().connect.Slot()

本文给你捋清楚它的具体使用,让你轻松掌握这一知识点,跨过这座大山。


知识点📖📖

本文用到的几个PySide6的知识点及链接。

作用链接
创建新线程QThread
对象间通信的机制,允许对象发送和接收信号Signal
用于响应Signal信号的方法Slot

基础概念

PySide6/PyQT 中的信号和槽是一种对象间通信机制。

信号(Signal)槽(Slot)
事件的发射者对事件的响应
在对象中定义的方法,在特定事件发生时被触发响应信号的函数,在信号发生时被调用

理解 信号和槽

用通俗易懂的话解释 PySide6/PyQT的信号和槽:

PySide6/PyQT信号和槽 机制简单地理解为一种 订阅机制

  • 信号充当了 发布者publisher)的角色,负责发布消息;
  • 槽扮演了 订阅者subscriber)的角色,用于接收消息并作出响应。
  • 槽可以订阅一个或多个信号,当信号发生时,槽会自动被调用执行。

信号 Signal

PySide6/PyQT中,可以使用 Signal 来定义信号。

信号 是一种特殊函数,可以在特定的情况下被 QObject 对象 发射(emit)

  • 下面代码定义了一个名为 my_signal 的信号,它接受一个整形参数(可以为空,也可以更换为其它类型
from PySide6.QtCore import (QThread, Signal)


class MyThread(QThread):
    my_signal = Signal(int)

槽 Slot

PySide6/PyQT中,可以使用 @Slot()装饰器 来定义

是普通的函数,它可以被信号调用。当一个信号被发射时,与之相连接的槽将被调用,并将信号的参数传递给槽。

  • 下面定义了一个名为 my_slot 的槽,它接受一个字符串参数,并打印接收到的数据
from PySide6.QtCore import (QThread, Slot)


class MyThread(QThread):
    
    @Slot(int)
    def my_slot(self, data):
        print("Received data: ", data)

值得注意是:

  • 这里的 Slot(int) 可以不写,但是写了可以提高代码可读性和执行效率。
  • 首先,标明这是一个槽函数;
  • 其次,在运行时动态地连接信号,在一定程度上提高代码的执行效率,因为在编译期间不需要生成额外的代码来连接信号和槽。

连接信号和槽

PySide6/PyQT 中,可以使用 connect() 方法将信号和槽相连接,如下所示:

  • 下面代码将sender对象的my_signal信号receiver对象的my_slot槽相连接。
  • sender对象发射my_signal信号时,receiver对象的my_slot槽将被调用。
sender = MyThread()
receiver = MyThread()

sender.my_signal.connect(receiver)

其实就是 使用 connect 将两者连接起来;


注意事项

重要的事情要强调三遍!



信号和槽只能在 QObject的子类里使用!!!

信号和槽只能在 QObject的子类里使用!!!

信号和槽只能在 QObject的子类里使用!!!


然而,在PySide6/PyQT 中,大部分常用的类都是继承了QObject类的,所以这个问题倒无需担心,只需知道有这一概念即可。


信号和槽必须是相同的参数类型。在定义信号和槽时,必须确保它们的参数类型和个数是相同的,否则无法正确连接和触发信号和槽。

信号和槽必须是相同的参数类型。在定义信号和槽时,必须确保它们的参数类型和个数是相同的,否则无法正确连接和触发信号和槽。

信号和槽必须是相同的参数类型。在定义信号和槽时,必须确保它们的参数类型和个数是相同的,否则无法正确连接和触发信号和槽。



常见异常

如果在非 QObject 的子类中使用 SignalSlot会遇到一些异常情况。这是因为在非 QObject 的子类中没有定义 Signalslot,也没有 QObject 提供的信号和槽管理机制。

在非 QObject 的子类中使用 SignalSlot,会遇到以下异常情况:

  • 定义 Signal 时会出现 NameError,因为 Signal是在 QObject 中定义的;
  • connect() 时会出现 AttributeError,因为 connect()QObject 的成员函数;
  • 在 信号emit() 时会出现 AttributeError,即属性错误,因为该类中没有该函数。

信号和槽 的基本使用

说完了 基础概念,现在上代码来检验学习成果了。

代码

# -*- coding: utf-8 -*-

import time


from PySide6.QtCore import (QThread, Signal, Slot, QSize)
from PySide6.QtWidgets import (QApplication, QPushButton, QLabel, QVBoxLayout, QWidget)


class MyThread(QThread):
    my_signal = Signal(int)
    finished_signal = Signal()

    def __init__(self, count):
        super().__init__()
        self.count: int = count

    def run(self):
        for idx in range(1, self.count + 1):
            time.sleep(1)
            # 任务进行时发出信号
            self.my_signal.emit(idx)
	    # 任务完成后发出信号
        self.finished_signal.emit()


class MainWindow(QWidget):

    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.setup_ui()
        #
        self.button.clicked.connect(self.setup_thread)

    def setup_ui(self):
        self.setWindowTitle('demo')
        self.resize(QSize(250, 180))
        # 创建一个垂直布局
        layout = QVBoxLayout()
        # 创建一个标签
        self.label = QLabel('This is a label => ')
        layout.addWidget(self.label)
        # 创建一个按钮
        self.button = QPushButton('Send Request')
        layout.addWidget(self.button)
        # 将布局设置为主窗口的布局
        self.setLayout(layout)
        # 显示窗口
        self.show()

    def setup_thread(self):
        self.thread_ = MyThread(count=5)
        self.thread_.my_signal.connect(self.thread_progress)
        self.thread_.finished_signal.connect(self.thread_finished)
        self.thread_.start()

    @Slot(int)
    def thread_progress(self, item):
        self.label.setText('This is a label => ' + str(item))

    @Slot()
    def thread_finished(self):
        self.label.setText('This is a label finished.')


if __name__ == '__main__':
    app = QApplication([])
    window = MainWindow()
    window.show()
    app.exec()

MyThread

  • 继承了 QObject,创建了一个名为 MyThreadQThread 类;
  • 包含一个名为my_signalfinished_signal 的信号,它们分别在 任何进行时任务完成后 发射;
  • 注意 my_signal 是带参数的,而 finished_signal 不带参数,这个需要与 槽函数对应!!!
  • 循环执行 count 次数的操作,每次 通过 my_signal 发射,从而修改 应用程序中的 lable
  • 当循环完成后,通过 finished_signal 发射信号,修改 应用程序中的 label

MainWindow

  • 继承了 QWidget,实现了包含一个按钮和一个标签的简单窗口;
  • setup_thread 函数中,实例化了MyThread,并将实例化后的 my_signal 和 finished_signal 信号连接到 thread_progress 和 thread_finished 函数;
  • thread_progress 和 thread_finished为槽函数,当my_signal 和 finished_signal发出信号时,对应Slot(槽函数)将被调用,并修改label 的显示。

运行效果

在这里插入图片描述

后话

本次分享到此结束,
see you~🐱‍🏍🐱‍🏍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/479593.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux】win10远程控制Linux服务器 - 内网穿透实现公网远程

Yan-英杰的主页 悟已往之不谏 知来者之可追 C程序员,2024届电子信息研究生 目录 前言 视频教程 1. ubuntu安装XRDP 2.局域网测试连接 3. Ubuntu安装cpolar内网穿透 4.cpolar公网地址测试访问 5.固定域名公网地址 [TOC] 转载自远程穿透文章:Wi…

Redis的两种持久化方案 RDB AOF

文章目录 1.RDB持久化1.1.执行时机1.2.RDB原理1.3.小结 2.AOF持久化2.1.AOF原理2.2.AOF配置2.3.AOF文件重写 3.RDB与AOF对比 Redis有两种持久化方案: RDB持久化AOF持久化 1.RDB持久化 RDB全称Redis Database Backup file(Redis数据备份文件&#xff09…

【三十天精通Vue 3】 第二十三天 Vue 3的错误处理详解

✅创作者:陈书予 🎉个人主页:陈书予的个人主页 🍁陈书予的个人社区,欢迎你的加入: 陈书予的社区 🌟专栏地址: 三十天精通 Vue 3 文章目录 引言一、Vue 3 错误处理概览1. 错误处理的重要性2. Vue 3 中的错误…

EMS快递批量分析物流信息状况

众所周知“邮政快递”是在快递行业里面也是算一家行业龙头,中国邮政特快专递/EMS,邮政平邮小包,邮政挂件等,都是属于中国邮政集团,邮政速度快,价格也是比较实惠一家,所以很多产家或电商 、供应商…

大数据-玩转数据-FLINK快速上手

一、环境准备 ⚫系统环境为 Windows 10。 ⚫需提前安装 Java 11。 ⚫集成开发环境(IDE)使用 IntelliJ IDEA,具体的安装流程参见 IntelliJ 官网。 ⚫安装 IntelliJ IDEA 之后,还需要安装一些插件——Maven 和 Git。Maven 用来管理…

Java实现宿舍管理系统的设计与实现【附源码】

本科生毕业论文(设计) 宿舍管理系统的设计与实现 目 录 摘 要 I Abstract II 1 引言 1 1.1 研究背景 1 1.2 国内外研究现状 1 1.3 研究目的与意义 1 2 开发工具和相关技术 2 2.1 Eclipse 2 2.2 MySQL 2 2.3 Bootstrap 3 2.4 Tomcat 3 3 系统分析 3 3.1…

Java基础学习(11)

Java基础学习 一、集合进阶1.1 数据结构(树)1.1.1 二叉查找树1.1.2 二叉树的遍历 1.2 平衡二叉树树的演变 1.3 数据结构 ( 平衡二叉树 )左旋1.4 数据结构 ( 平衡二叉树 )右旋数据结构 (平衡二叉树)需要转的四种情况 1.5 红黑树添加节点规则 二、Set系列集…

基础算法(五):DFS、BFS与剪枝

前言 前面的基础算法笔记已经断更好久了,因为荔枝觉得还是得先学一下基础的数据结构知识之后才能更好的入门算法。在这篇文章中荔枝主要记录DFS和BFS的相关基础知识、答题的模板以及自己的一些浅薄理解,同样的也会涉及到相关的剪枝操作。 一、搜索算法概…

java基础学习-7

文章目录 异常小总结编译时异常和运行时异常小总结 异常在代码中的两个作用异常的方式JVM虚拟机默认处理异常的方式自己处理(捕获异常)灵魂四问抛出异常异常中的常见方法小总结小练习 自定义异常 File----路径File的概述和构造方法小总结 File的成员方法…

线性表之顺序表(C语言实现)

前言 🎈个人主页:🎈 :✨✨✨初阶牛✨✨✨ 🐻推荐专栏: 🍔🍟🌯 c语言初阶 🔑个人信条: 🌵知行合一 🍉本篇简介:>:讲解数据结构的入门知识,线性结构之顺序表. 金句分享:…

机器学习笔记 基于深度学习的边缘检测

一、Holistically-Nested Edge Detection 边缘检测是视觉工作中十分常用的技术,传统边缘检测已经包含了很多经典的诸如Canny、Robert等等,都是各有擅场,不过有一点问题,就是很多参数需要人工调试,所以深度学习研究人员提出了基于卷积神经网络的边缘检测算法。 即HED,该算…

uniapp拍照离线定位,获取图片信息,经纬度解析地址

✅作者简介: 我是痴心阿文,你们的学友哥,今天给大家分享uniapp拍照离线定位,获取图片信息,经纬度解析地址 📃个人主页:痴心阿文的博客_CSDN博客-Vue.js,数组方法,前端领域博主 🔥本文前言&#…

【数据结构】超详细之顺序表(利用C语言实现)

文章目录 前言一、顺序表是什么?二、顺序表的实现步骤 1.顺序表的初始化以及开辟空间2.实现顺序表的头插、尾插以及打印3.实现顺序表的头删、尾删以及打印4.实现顺序表的查找5.实现顺序表指定位置插入6.实现顺序表指定位置删除7.释放内存总结 前言 数据结构是一个程…

离散数学_九章:关系(3)

9.3 关系的表示 1、用集合表示关系2、用矩阵表示关系矩阵表示关系⭐集合上的关系矩阵 R 自反时 R 对称时 R 反对称时 ⭐确定关系合成的矩阵 3、用有向图表示关系有向图⭐从有向图中 确定关系具有的属性 自反性对称性反对称性传递性 本节及本章的剩余部分研究的所有关系均为二…

函数(详解)——C语言

Hello,友友们前段时间忙拖更了这么久,趁着五一假期好好卷上一波哈哈哈。好的,我们本期主要对C语言中的函数进行讲解。 1.什么是函数 在数学中也常常用到函数,但你对C语言中的函数有了解吗? 在C语言中函数是一段可重…

数据结构学习分享之单链表详解

数据结构第三课 1. 前言2. 链表的概念以及结构3. 链表的分类4.链表的实现4.1 初始化结构4.2 尾插函数4.3 尾删函数4.4 头插函数4.5 头删函数4.6 开辟新节点4.7 销毁链表 5. 单链表OJ题目6. 顺序表和链表的区别7. 总结 1. 前言 💓博主CSDN:杭电码农-NEO💓…

五年开发经验前端程序员,刚入职一个月就要离职,我来聊聊看法

最近有一个新来的同事,估计又要离职了吧。从他的工作经历来看,大概有5年的前端工作经验,但是头发看起来挺少的,不知道是工作加班导致的,看他的性格不太像是经常加班的。 他这个人就是我们公司人事面试的,虽…

操作系统——进程管理

0.关注博主有更多知识 操作系统入门知识合集 目录 0.关注博主有更多知识 4.1进程概念 4.1.1进程基本概念 思考题: 4.1.2进程状态 思考题: 4.1.3进程控制块PCB 4.2进程控制 思考题: 4.3线程 思考题: 4.4临界资源与临…

躺平减脂减重法补充篇——无需控制碳水摄入的有效方法,另推一种健康的运动和防止老年慢性病的方式...

本文此前已经连续发表了六篇相关文章,内容确实比较多,最近又做了一组实验,进食了大量的锅巴,看看是否会带来体重的增加,每天进食量都不少于200克锅巴,对,4两重,而且是在每天正常进食…

SAPUI5 之XML Views (视图) 笔记

文章目录 官网 Walkthrough学习-XML Views视图案例要求:我们把上面通过index.html body的展示放在XML中展示1.0.1 新增view文件夹1.0.2 在xml文件中新增一个Text 文本1.0.3 在index.js中实例化view视图1.0.4 执行刷新浏览器1.0.5 调试界面分析结果 官网 Walkthrough…