PySide2学习总结(八)Qt的信号(Signal)和槽(Slot)

2023-12-28 06:38

本文主要是介绍PySide2学习总结(八)Qt的信号(Signal)和槽(Slot),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

在GUI编程过程中,经常需要进行通信的处理,往往需要各种类型的对象之间进行通信,比如,当用户点击了某个按钮,我们希望它调用某个功能输出一些提示信息。
在其他编程工具中往往使用“回调”技术来实现对象之间的通信。“回调”是将函数的指针(地址)作为参数传递给另一个处理函数,并在该函数内利用这个参数来调用原函数。

简介

在Qt中使用信号和槽(Signals and Slots)来实现其他编程工具包的“回调”功能。
信号和槽机制是 Qt 的主要特性并且也很有可能是它与其他框架特性区别最大的部分。
当一个特定的事件发生时,信号会被发送出去,而槽则被用来接收信号。

信号和槽

Qt的窗体部件(widget)拥有众多预先定义好的信号,当然,我们也可以创建窗体部件(widget)的子类来为它们添加自定义信号。
槽,则是对一个特定的信号进行的反馈。Qt的窗体部件(widget)同样拥有众多预先定义好的槽,但是通常的做法是,创建窗体部件(widget)的子类并添加自定义槽,以便对特定的信号进行处理。

信号-槽机制是类型安全的:一个信号的签名(参数类型)必须与它的接收槽的签名相匹配。
信号和插槽是松散耦合的:一个发射信号的类不用知道也不用关心哪个槽要接收这个信号。
信号和槽可以使用任何数量、任何类型的参数。

对象中以这种方式通信:当对象改变其状态时,信号就由该对象发射 (emit) 出去,这就是对象所要做的全部事情,发送信号的对象不需要知道什么对象接收它所发出的信号,这是真正的信息封装,保证了对象能被当作软件组件来使用。而关心这个改变的另一对象则会接收这个信号。

槽能被用来接收信号,除此之外它们也是普通的成员函数。槽不知道是否有信号与它连接起来,正如对象不知道它发出信号是否会被接收一样。这样的机制确保了可以使用Qt创建一个个完全独立的组件。

信号与槽之间可以一对一连接,也可以把一个信号与多个槽进行连接。甚至可以直接把一个信号连接到另一个信号(当第一个信号发送出去的时候,第二个信号紧接着被发送)。信号-槽机制完全独立于任何 GUI 事件循环。只有当所有的槽返回以后发射函数(emit)才返回。如果存在多个槽与某个信号相关联,那么,当这个信号被发射时,这些槽将会一个接一个地执行,但是它们执行的顺序将会是随机的、不确定的,我们不能人为地指定哪个先执行、哪 个后执行。

就这样,信号与插槽建立了强大的组件编程机制。

编程示例

简单例子

这里使用了前面的button示例的代码:

import sys
from PySide2.QtWidgets import QApplication, QPushButton
from PySide2.QtCore import Slot# @Slot()是一个装饰器,标志着这个函数是一个slot(槽)
@Slot()
def output():
"""在控制台输出内容"""print("Button clicked")app = QApplication(sys.argv)
# 创建一个button
button = QPushButton("clicked me")
# 将信号和槽进行连接
button.clicked.connect(output)
button.show()app.exec_()

在这个例子中,我们定义了一个槽output()和一个按钮的点击信号,并通过connect将二者进行连接。这样,当点击按钮时槽就会接收到这个点击信号,相当于调用了output()。

带参数示例

当使用带有参数的信号和槽时,在定义的时候,需要注意声明所带的参数类型。

import sys
from PySide2.QtWidgets import QApplication
from PySide2.QtCore import QObject, Signal, Slot# 定义一个带有字符串参数的槽
@Slot(str)
def output(str):print(str)class Test(QObject):# 自定义一个信号output_str = Signal(str)output_key = Test()
output_key.output_str.connect(output)
# 发射信号
output_key.output_str.emit("Signal emit with para")app = QApplication(sys.argv)
app.exec_()

运行效果如图:
在这里插入图片描述

多个信号连接一个槽

当多个信号传入不同类型参数时,需要增加槽所能接收的参数类型:

import sys
from PySide2.QtWidgets import QApplication
from PySide2.QtCore import QObject, Signal, Slot# 增加槽的可接收参数类型
@Slot(str)
@Slot(int)
def output(str):print(str)class Test(QObject):# 自定义不同参数类型的信号output_str = Signal(str)output_int = Signal(int)output_key = Test()
output_key.output_str.connect(output)
output_key.output_int.connect(output)
# 发射信号
output_key.output_str.emit("Signal emit with para")
output_key.output_int.emit(111)app = QApplication(sys.argv)
app.exec_()

运行效果如图:
在这里插入图片描述
当每次只传入其中一种参数时,可以改写成如下形式:

import sys
from PySide2.QtWidgets import QApplication
from PySide2.QtCore import QObject, Signal, Slot# 增加槽的可接收参数类型
@Slot(str)
@Slot(int)
def output(str):print(str)class Test(QObject):# 自定义不同参数类型的信号# 声明可接收的参数类型,但每次只能够接收其中一种output_str = Signal((str,),(int,))output_key = Test()
# 未对参数类型进行设置即默认为第一个参数类型
output_key.output_str.connect(output)
output_key.output_str[int].connect(output)
# 发射信号
output_key.output_str.emit("Signal emit with para")
output_key.output_str[int].emit(111)app = QApplication(sys.argv)
app.exec_()

当需要同时传入多种类型参数时,只需要添加多个参数并一一声明类型即可:

import sys
from PySide2.QtWidgets import QApplication
from PySide2.QtCore import QObject, Signal, Slot# 增加槽的接收参数
@Slot(str)
@Slot(int)
def output(str, int):print(str, int)class Test(QObject):# 自定义不同参数类型的信号# 声明可接收的参数类型,但每次只能够接收其中一种output_str = Signal(str, int)output_key = Test()
output_key.output_str.connect(output)
# 发射信号
output_key.output_str.emit("Signal emit with para", 111)app = QApplication(sys.argv)
app.exec_()

代码整理

import sys
from PySide2.QtWidgets import QApplication                                                                  
from PySide2.QtCore import QObject, Signal, Slotclass Test(QObject): output_str = Signal((str, int), (str,))     def __init__(self): super(Test, self).__init__()self.output_str[str].connect(self.output)self.output_str[str, int].connect(self.output_two)def exec_emit(self):self.output_str[str].emit("Signal emit with para")self.output_str[str, int].emit("Signal emit with para", 111)@Slot(int)@Slot(str)def output(self, str_or_int):print(str_or_int)@Slot(int)@Slot(str)def output_two(self, str, int):print(str, int)output_key = Test()
output_key.exec_emit()app = QApplication(sys.argv)
app.exec_()

运行效果如图:
在这里插入图片描述

这篇关于PySide2学习总结(八)Qt的信号(Signal)和槽(Slot)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/545241

相关文章

Python中实现进度条的多种方法总结

《Python中实现进度条的多种方法总结》在Python编程中,进度条是一个非常有用的功能,它能让用户直观地了解任务的进度,提升用户体验,本文将介绍几种在Python中实现进度条的常用方法,并通过代码... 目录一、简单的打印方式二、使用tqdm库三、使用alive-progress库四、使用progres

基于Qt Qml实现时间轴组件

《基于QtQml实现时间轴组件》时间轴组件是现代用户界面中常见的元素,用于按时间顺序展示事件,本文主要为大家详细介绍了如何使用Qml实现一个简单的时间轴组件,需要的可以参考下... 目录写在前面效果图组件概述实现细节1. 组件结构2. 属性定义3. 数据模型4. 事件项的添加和排序5. 事件项的渲染如何使用

基于Qt开发一个简单的OFD阅读器

《基于Qt开发一个简单的OFD阅读器》这篇文章主要为大家详细介绍了如何使用Qt框架开发一个功能强大且性能优异的OFD阅读器,文中的示例代码讲解详细,有需要的小伙伴可以参考一下... 目录摘要引言一、OFD文件格式解析二、文档结构解析三、页面渲染四、用户交互五、性能优化六、示例代码七、未来发展方向八、结论摘要

无线路由器哪个品牌好用信号强? 口碑最好的三个路由器大比拼

《无线路由器哪个品牌好用信号强?口碑最好的三个路由器大比拼》不同品牌在信号覆盖、稳定性和易用性等方面各有特色,如何在众多选择中找到最适合自己的那款无线路由器呢?今天推荐三款路由器让你的网速起飞... 今天我们来聊聊那些让网速飞起来的路由器。在这个信息爆炸的时代,一个好路由器简直就是家庭网编程络的心脏。无论你

Android数据库Room的实际使用过程总结

《Android数据库Room的实际使用过程总结》这篇文章主要给大家介绍了关于Android数据库Room的实际使用过程,详细介绍了如何创建实体类、数据访问对象(DAO)和数据库抽象类,需要的朋友可以... 目录前言一、Room的基本使用1.项目配置2.创建实体类(Entity)3.创建数据访问对象(DAO

电脑显示hdmi无信号怎么办? 电脑显示器无信号的终极解决指南

《电脑显示hdmi无信号怎么办?电脑显示器无信号的终极解决指南》HDMI无信号的问题却让人头疼不已,遇到这种情况该怎么办?针对这种情况,我们可以采取一系列步骤来逐一排查并解决问题,以下是详细的方法... 无论你是试图为笔记本电脑设置多个显示器还是使用外部显示器,都可能会弹出“无HDMI信号”错误。此消息可能

Java向kettle8.0传递参数的方式总结

《Java向kettle8.0传递参数的方式总结》介绍了如何在Kettle中传递参数到转换和作业中,包括设置全局properties、使用TransMeta和JobMeta的parameterValu... 目录1.传递参数到转换中2.传递参数到作业中总结1.传递参数到转换中1.1. 通过设置Trans的

C# Task Cancellation使用总结

《C#TaskCancellation使用总结》本文主要介绍了在使用CancellationTokenSource取消任务时的行为,以及如何使用Task的ContinueWith方法来处理任务的延... 目录C# Task Cancellation总结1、调用cancellationTokenSource.

python与QT联合的详细步骤记录

《python与QT联合的详细步骤记录》:本文主要介绍python与QT联合的详细步骤,文章还展示了如何在Python中调用QT的.ui文件来实现GUI界面,并介绍了多窗口的应用,文中通过代码介绍... 目录一、文章简介二、安装pyqt5三、GUI页面设计四、python的使用python文件创建pytho

QT实现TCP客户端自动连接

《QT实现TCP客户端自动连接》这篇文章主要为大家详细介绍了QT中一个TCP客户端自动连接的测试模型,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录版本 1:没有取消按钮 测试效果测试代码版本 2:有取消按钮测试效果测试代码版本 1:没有取消按钮 测试效果缺陷:无法手动停