PyQt5 信号(Signal)与槽(Slot)

news2024/11/25 3:06:12

PyQt5 信号与槽

  • 信号与槽介绍
  • 内置信号与槽的使用
  • 自定义信号与槽的使用
  • 自定义信号和内置槽函数
  • 自定义信号和自定义槽函数
  • 自定义有参信号
  • 使用自定义信号参数
  • 装饰器信号与槽
  • 信号与槽的断开和连接
  • 多线程中信号与槽的使用

信号与槽介绍

信号(Signal)与槽(Slot)是Qt中的核心机制,也是在PyQt编程中对象之间进行通信的机制。PyQt的窗口控件类有很多内置信号,开发者也可以添加自定义信号。信号与槽有如下特点:

  • 一个信号可以连接多个槽。
  • 一个信号可以连接另一个信号。
  • 信号参数可以使任何Python类型。
  • 一个槽可以连接到多个信号。
  • 信号与槽的连接方式可以是同步连接,也可以是异步连接。
  • 信号与槽的连接可能会跨线程。
  • 信号可以断开连接。

内置信号与槽的使用

这里演示了内置clicked信号连接槽函数的使用

import sys
from PyQt5.QtWidgets import QPushButton, QApplication, QWidget, QMessageBox

app = QApplication(sys.argv)
widget = QWidget()

def showMsg():
    QMessageBox.information(widget, "信息提示框", "Ok,弹出测试信息")

btn = QPushButton("测试点击按钮", widget)
btn.clicked.connect(showMsg)

widget.show()
sys.exit(app.exec_())

在这里插入图片描述

自定义信号与槽的使用

import sys
from PyQt5.QtCore import QObject, pyqtSignal


# 信号对象
class QTypeSignal(QObject):
    # 定义一个信号
    sendmsg = pyqtSignal(object)

    def __init__(self):
        super(QTypeSignal, self).__init__()
    
    def run(self):
        # 发射信号
        self.sendmsg.emit('Hello PyQt5')

# 槽对象
class QTypeSlot(QObject):
    def __init__(self):
        super(QTypeSlot, self).__init__()

    # 槽对象中的槽函数
    def get(self, msg):
        print("QSlot get msg => " + msg)

if __name__ == "__main__":
    send = QTypeSignal()
    slot = QTypeSlot()

    # 1
    print("---把信号绑定到槽函数上---")
    send.sendmsg.connect(slot.get)
    send.run()

    # 2 
    print('---把信号与槽函数断开---')
    send.sendmsg.disconnect(slot.get)
    send.run()

在这里插入图片描述

自定义信号和内置槽函数

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtCore import Qt

class WinForm (QWidget):
    # 自定义信号,不带参数
    button_clicked_signal = pyqtSignal()

    def __init__(self, parent=None):
        super(WinForm, self).__init__(parent)
        self.setWindowTitle("自定义信号和内置槽函数示例")
        self.resize(330, 50)
        btn = QPushButton("关闭", self)

        # 连接信号与槽函数
        btn.clicked.connect(self.btn_clicked)
        
        # 接收信号,连接到槽函数
        self.button_clicked_signal.connect(self.close)

    def btn_clicked(self):
        # 发送自定义信号,无参数
        self.button_clicked_signal.emit()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = WinForm()
    win.show()
    sys.exit(app.exec_())

自定义信号和自定义槽函数

import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

class WinForm(QWidget):
    # 自定义信号,无参数
    button_clicked_signal = pyqtSignal()
    def __init__(self, parent= None):
        super(WinForm, self).__init__(parent)
        self.setWindowTitle("自定义信号和槽函数示例")
        self.resize(350, 50)

        btn = QPushButton("关闭", self)
        btn.clicked.connect(self.btn_clicked)
        self.button_clicked_signal.connect(self.btn_close)
    
    def btn_clicked(self):
        self.button_clicked_signal.emit()

    def btn_close(self):
        self.close()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = WinForm()
    win.show()
    sys.exit(app.exec_())    

自定义有参信号

import sys
from PyQt5.QtCore import pyqtSignal, QObject

class CustSignal(QObject):
    # 声明无参数的信号
    signal1 = pyqtSignal()

    # 声明带一个int类型参数的信号
    signal2 = pyqtSignal(int)

    # 声明带一个int和一个str类型参数的信号
    signal3 = pyqtSignal(int, str)

    # 声明带一个列表类型参数的信号
    signal4 = pyqtSignal(list)

    # 声明带一个字典类型参数的信号
    signal5 = pyqtSignal(dict)

    # 声明一个多重载版本的信号,包括带int和str类型参数的信号和带str类型参数的信号
    signal6 = pyqtSignal([int,str], [str])

    def __init__(self, parent=None):
        super(CustSignal, self).__init__(parent)
        
        # 将信号连接到指定的槽函数
        self.signal1.connect(self.signalCall1)
        self.signal2.connect(self.signalCall2)
        self.signal3.connect(self.signalCall4)
        self.signal4.connect(self.signalCall4)
        self.signal5.connect(self.signalCall5)
        self.signal6[int, str].connect(self.signalCall6)
        self.signal6[str].connect(self.signalCall6OverLoad)

        # 发射信号
        self.signal1.emit()
        self.signal2.emit(100)
        self.signal3.emit(200, 'hello')
        self.signal4.emit([1,2,3,4,5,6])
        self.signal5.emit({"name":"xiaowang", "age":"25"})
        self.signal6[int, str].emit(300, 'hello world')
        self.signal6[str].emit('hello pyqt')

    def signalCall1(self):
        print('signal1 emit')
    
    def signalCall2(self, val):
        print('signal3 emit, value:', val)
    
    def signalCall3(self, val, text):
        print('signal3 emit, value:', val, text)

    def signalCall4(self, val):
        print('signal4 emit, value:', val)
    
    def signalCall5(self, val):
        print('signal5 emit, value:', val)

    def signalCall6(self, val, text):
        print('signal6 emit, value:', val, text)

    def signalCall6OverLoad(self, val):
        print('signal6 overload emit, value:', val)

if __name__ == "__main__":
    custSignal = CustSignal()
  

使用自定义信号参数

对于clicked信号来说他是没有参数的,如果连接的槽函数希望可以接收参数,如果直接连接有参数的槽函数会出错,因为信号发出的参数个数一定要大于槽函数接收的参数个数。这里有两种解决方法:

  • 1.使用lambda
  • 2.使用functools模块中的partial函数
import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from functools import partial, partialmethod

class WinForm(QMainWindow):
    def __init__(self, parent=None):
        super(WinForm, self).__init__(parent)
        self.setWindowTitle("有参槽函数接收无参信号的解决方法")

        button1 = QPushButton("Button 1")
        button2 = QPushButton("Button 2")

        # 对于clicked信号来说他是没有参数的,如果连接的槽函数希望可以接收参数,如果直接连接有参数
        # 的槽函数会出错,因为信号发出的参数个数一定要大于槽函数接收的参数个数。这里有两种解决方法:
        # 1.使用lambda
        # 2.使用functools模块中的partial函数
        
        # 使用lambda
        button1.clicked.connect(lambda: self.onButtonClick(1))

        # 使用functools模块中的partial函数
        button2.clicked.connect(partial(self.onButtonClick, 2))

        layout = QHBoxLayout()
        layout.addWidget(button1)
        layout.addWidget(button2)
        mainwidget = QWidget()
        mainwidget.setLayout(layout)
        self.setCentralWidget(mainwidget)


    def onButtonClick(self, n):
        print("Button {0} 被按下了".format(n))
        QMessageBox.information(self, "信息提示框", 'Button {0} clicked'.format(n))

if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = WinForm()
    win.show()
    sys.exit(app.exec_())

装饰器信号与槽

装饰器信号与槽
@PyQt5.QtCore.pyqtSlot(参数)
def on_发送者对象名称_发射信号名称(self, 参数):
pass
必须先执行了这行代码:QtCore.QMetaObject.connectSlotsByName(self)

from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QPushButton, QMessageBox
import sys

# 装饰器信号与槽
# @PyQt5.QtCore.pyqtSlot(参数)
# def on_发送者对象名称_发射信号名称(self, 参数):
#   pass
# 
# 必须要先执行这行代码:QtCore.QMetaObject.connectSlotsByName(self)

class CustWidget(QWidget):
    def __init__(self, parent=None):
        super(CustWidget, self).__init__(parent)
        self.setWindowTitle("装饰器信号与槽Demo")
        self.resize(350, 50)

        self.okButton = QPushButton("OK", self)

        # 使用setObjectName设置对象名称
        self.okButton.setObjectName("okButton")
        layout = QHBoxLayout()
        layout.addWidget(self.okButton)
        self.setLayout(layout)

        QtCore.QMetaObject.connectSlotsByName(self)


    @QtCore.pyqtSlot()
    def on_okButton_clicked(self):
        print("单击了OK按钮")
        QMessageBox.information(self, "信息提示框", "单击了OK按钮")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = CustWidget()
    win.show()
    sys.exit(app.exec_())

信号与槽的断开和连接

import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *


# 信号与槽断开连接

class SignalClass(QObject):
    # 声明无参数的信号
    signal1 = pyqtSignal()

    # 声明带一个int类型参数的信号
    signal2 = pyqtSignal(int)

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

        # 将信号signal1连接到sig1Call和sig2Call这两个槽函数
        self.signal1.connect(self.sig1Call)
        self.signal1.connect(self.sig2Call)

        # 将signal2连接到signal1
        self.signal2.connect(self.signal1)

        # 发射信号
        self.signal1.emit()
        self.signal2.emit(1)

        # 断开signal1,signal2信号与各槽函数的连接
        self.signal1.disconnect(self.sig1Call)
        self.signal1.disconnect(self.sig2Call)
        self.signal2.disconnect(self.signal1)
        
        # 将信号signal1和signal2连接到同一个槽函数sig1Call
        self.signal1.connect(self.sig1Call)
        self.signal2.connect(self.sig1Call)

        # 再次发射信号
        self.signal1.emit()
        self.signal2.emit(2)

    def sig1Call(self):
        print('signal-1 emit')
    
    def sig2Call(self):
        print('signal-2 emit')

if __name__ == "__main__":
    signal = SignalClass()

多线程中信号与槽的使用

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

class Main(QWidget):
    def __init__(self, parent=None):
        super(Main, self).__init__(parent)

        # 创建一个线程实例并设置名称,变量,信号与槽
        self.thread = MyThread()
        self.thread.setIdentity("thread1")
        self.thread.sinOut.connect(self.outText)
        self.thread.setVal(6)
        
    def outText(self, text):
        print(text)

class MyThread(QThread):
    
    sinOut = pyqtSignal(str)

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

    def setIdentity(self, text):
        self.identity = text
    
    def setVal(self, val):
        self.times = int(val)
        # 执行线程run方法
        self.start()

    def run(self):
        while self.times > 0 and self.identity:
            # 发射信号
            self.sinOut.emit(self.identity + "==>" + str(self.times))
            self.times -= 1

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

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

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

相关文章

基于Spring Boot的个人博客系统(源码+数据库)

目录 一、系统功能框架图 二、开发技术 三、开发环境 四、页面展示 1.登录页面 2.首页 3.文章详情页面 4.文章评论页面 ​5.后台页面 6.后台文件编辑页面 ​7.后台文章管理列表页面 五、文件组织结构 六、数据库设计 1. 文章详情表t_article 2.文章评论表t_comm…

Elasticsearch:构建地图以按国家或地区比较指标

标如果你不熟悉 Elastic 地图,本教程是一个不错的起点。 它会指导你完成处理位置数据的常见步骤。在完成本教程后,你将学会: 创建具有多个图层和数据源的地图使用符号、颜色和标签来设置数据值的样式在仪表板中嵌入地图在仪表板中跨仪表盘搜索 完成本教…

【Scala专栏】数据类型、变量常量、类和对象

本文内容主要分为3节,依次讲解:Scala的数据类型有哪些? 变量常量如何使用? 类和对象如何理解? 受限于博主的大脑容量,大概是无法做到事无巨细的,不过其实也没必要那么"细"&#xff0c…

Java核心技术卷Ⅰ-第三章Java的基本程序设计结构

重点 1.数据类型 2.运算符 3.字符串 4.控制流程 5.数组 1.数据类型 整型:Java程序必须保证在所有机器上都能得到相同的运行结果,所以各种数据类型的取值范围是固定的;在C/C中,int和long类型的大小与目标平台相关 类型存储需求取值…

基于粒子群算法的线性规划问题求解matlab程序

基于粒子群算法的线性规划问题求解matlab程序 1 基本粒子群算法流程 粒子群算法基于“种群”和“进化”的概念,通过个体间的协作与竞争,实现复杂空间最优解的搜索,其流程如下: (1)初始化粒子群&#xff…

Apache Maven

Apache Maven简介安装Eclipse中安装内置的Maven插件Maven官网下载,直接安装在电脑上Maven安装目录结构bin目录boot目录conf目录lib目录Maven生命周期与命令Maven生命周期clean:清理cleanup:清理所有default:默认site:站…

做数据集增强时,训练一半出现IndexError: tuple index out of range这种错误,不知道怎么改,有神仙赐教一下嘛?

在用YOLOv5做图像训练时,首先做了数据集的增强,但是增强中出现了如下的错误 首先出现这样的警告 (A:/stdy py37-g/agu_img.py:153: DeprecationWarning: An exception was ignored while fetching the attribute __array_interface__ from an object of …

maven部署方案之分离业务包

一、思想: 通过将业务包和公共包分离,集中管理所有包,打包时只构建业务包减少项目包的大小和传输时间。 为了观测稳定性,暂通过环境区分,较为频繁的联调环境采用该方式,测试、预发、正式暂保持一体化打包…

golang实现andflow流程引擎

1、andflow引擎 andflow_js可以实现在Html端设计流程,并将设计结果保存为json模型,andflow可以用于设计业务流程、数据处理流程、工作流、控制流等一切可流程化的过程。 由于golang具备高效、跨平台、并且还能够直接编译成可执行文件,这些优…

selenium 找不到元素:Unable to find element on closed window

浏览器:IE 报错信息: Unable to find element on closed window Unable to get browser 过程:登录》跳转页面(同窗口)》点击备份按钮 已知代码没有改过,而且部署到多个机子上,很多机子没有问…

C++11(一)

🧸🧸🧸各位大佬大家好,我是猪皮兄弟🧸🧸🧸 文章目录一、列表初始化initializer_list二、声明1.auto2.decltype3.nullptr三、C11 STL中的变化1.array2.forward_list3.STL其他变化四、C关键字新功…

NOIP 装箱问题

题目:[NOIP2001]装箱问题 ,哈哈,我们今天来看一道很古老的题嘛,这是选自NOIP上的一道题,好了,我们一起来看看题意吧: 考虑到直接复制题目,或者截屏的方式不是很方便阅读&#xff0…

常见的网络协议

目录 一、TCP/IP协议簇 二、网络设备与五层模型对应关系: 三、常用网络协议总结(TCP/IP协议簇) 四、应用层服务协议 五、传输层协议组 TCP_UDP 六、网络层协议 IP_ICMP_ARP 七、物理层协议 MAC子层协议 一、TCP/IP协议簇 OSI七层模型…

视频怎么转换为音频文件?快来掌握这几种方式

大家平时在下载网课资源进行学习的时候,看久了眼睛也会开始疲劳,而且有些视频的画面看起来很枯燥。其实我们可以使用一些软件把视频中的音频分离出来,直接收听音频也可以学到知识,而且我们还可以处理其他的事情,是不是…

《计算机体系结构量化研究方法第六版》1.5 集成电路中的功耗和能耗趋势

1.5.1 功耗和能耗:系统视角 Q1:处理器需要的最大功耗是多少? 如果处理器的预期功耗大于电源系统能够提供的功耗(试图汲取的电流大于电源系统可以提供的电流),通常会导致电压下降而让器件无法工作。在峰值…

食谱类小程序开发,升级美食服务质量

网络时代,人们可以在网上快速获取到各种资源信息,疫情的影响让人们被封控在家里出不了门,这也就给人们提供了一个回归厨房的契机,很多人在此期间开启了自己的美食制作之旅,朋友圈也变成了一个美食分享社区,…

AlphaFold2源码解析(1)--安装使用

AlphaFold2源码解析(1)–安装使用 AlphaFold2有两种安装方式: 具体可以参考我之前写的博客: Alphafold docker 安装: 参考GitHub:https://github.com/deepmind/alphafold 一步一步安装就可以了, Alphafold 非docker 安装指南 如…

基于PHP+MySQL蚕豆酱厂管理系统的设计与实现

论文阐述了安庆市胡玉美蚕豆酱厂管理系统的设计与实现,并对该系统的需求分析及系统需要实现的设计方法作了介绍。该系统的基本功能包括用户登录,管理员信息管理,车间主任信息管理,采购员信息管理,生产计划管理&#xf…

【正点原子FPGA连载】 第十七章 HDMI彩条显示实验摘自【正点原子】DFZU2EG/4EV MPSoC 之FPGA开发指南V1.0

1)实验平台:正点原子MPSoC开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id692450874670 3)全套实验源码手册视频下载地址: http://www.openedv.com/thread-340252-1-1.html 第十七章 HDMI彩…

基于PLC控制四自由度气动式机械手设计

目 录 1 绪论 1 1.1 机械手的概述 1 1.2 机械手的发展史 1 1.3 气动技术及气动机械手的发展过程 2 1.4 机械手未来的发展趋势 3 1.5 本课题研究内容 4 1.6 课题研究的意义 4 2 机械手的总体设计方案 6 2.1 机械手的工作原理及系统组成 6 2.2 机械手基本形式的选择 7 2.3 驱动机…