第15.16节 PyQt(Python+Qt)入门学习:PyQt中的信号(signal)和槽(slot)机制以及Designer中的使用
一、引言
前面一些章节其实已经在使用信号和槽了,但是作为Qt中最重要的机制也是Qt区别与其他开发平台的重要核心特性,还是非常有必要单独介绍。
二、信号和槽的概念
2.1、概述
信号和槽是Qt特有的信息传输机制,是Qt设计程序的重要基础,它可以让互不干扰的对象建立一种联系。
信号和槽用于对象间的通信,在一个图形界面程序中,当一个部件中发生变化时,通常需要通知其他对象,在Qt中当采用特定事件发生时会发射(注意此处用的是发射(emit)而不是发送,老猿估计是因为这里的信号不是一对一发送的,而是可以一对多发射)一个信号来通知需要通知的对象,需要关注的对象就会调用信号连接的槽函数执行响应操作。
从QObject或其子类(如QWidget)继承的所有类都可以包含信号和插槽。
2.2、信号(signal)
当对象以其他对象可能感兴趣的方式改变其状态时,它们会发出信号。
Qt中的信号本质上是一个公有函数(即方法),信号只需声明,不能对其进行定义,声明函数时不能有返回值。由于信号是某个对象的公有方法,信号可以从任何地方通过emit语句发出,与直接调用信号对应函数类似,只是在函数调用语句前多了个emit。
发射信号的语句:emit 信号函数(信号参数)
Qt建议只从定义信号的类及其子类的类发出信号,Qt中的部件(又称为控件、组件)都有一些预定义的信号,如按钮的clicked()信号。信号发出方不知道也不关心是否有对象在接收它发出的信号
2.3、槽(slot)
槽可以用来接收信号,但槽也是部件派生类的正常成员函数,槽本质上是某个类的方法(包括虚方法),用来调用以响应特定信号,非虚函数的槽函数也可以正常调用,与普通成员方法的唯一的区别是信号可以连接到它们。
由于槽是普通成员方法,所以当直接调用时,它们遵循正常的成员方法调用规则。但是,作为槽,它们可以由任何组件通过信号连接调用,不管槽函数的访问级别是公开还是私有,信号的发射者无需知道哪些对象会执行槽函数响应它发射的信号(老猿认为由于Python的封装机制,这点在PyQt中意义不大)。
就像一个对象不知道是否有任何东西接收到它的信号一样,槽也不知道是否有任何信号连接到它。
2.4、处理信号
处理信号通常的做法是对可视部件进行子类化并添加对应的槽,以便处理感兴趣的信号。
当信号发
出时,通常与之相连的槽像正常的函数调用一样会立即执行,所有槽都返回后,将执行信号发出的emit语句后面的代码。但在信号和槽连接使用队列连接(connect函数的type参数值为Qt.QueuedConnection,使用Qt Designer定义的信号和槽连接通过PyUIC生成的代码不会使用该值)时情况略有不同,在这种情况下,emit关键字后面的代码将立即继续,槽将在稍后执行。
如果多个槽连接到一个信号,则当信号发射时,槽函数将按照建立连接的顺序依次执行。
与其他平台用于对象间通信的回调函数机制相比,信号和槽的机制稍微慢一些,发射与某些槽相连的信号,比用槽函数直接调用响应慢约十倍(不考虑槽函数本身的执行时间,只是从信号发射到槽函数开始执行的时间),但这种机制提供的灵活性增加了。
注意:
槽函数可能与多个对象的多个信号连接,有时代码需要判断信号是哪个对象发送的,此时可以使用在槽函数中使用sender()函数获取信号的发送对象来进行不同的处理。具体可参考:《PyQt学习随笔:槽函数获取信号发送对象的方法》
二、信号和槽的特点
2.1、信号和槽的参数必须匹配
Qt的signal s和slots机制确保,如果将一个信号连接到一个slot,该slot将在正确的时间使用信号的参数调用。在Qt中,信号和插槽可以接受任意数量的任何类型的参数,但老猿认为在PyQt中可能存在一些限制。
信号和槽的参数必须匹配体现在以下方面:
- 信号和槽的签名(英文原文是signature,老猿理解签名就是所带的参数)必须匹配,槽的参数可以少于信号的参数数量,因为槽函数可以忽略额外的参数,槽的参数不能多余信号的参数,因为若槽的参数更多,则多余的参数不能接收到信号传递过来的值,若在槽中使用了这些多余的无值的参数,就会产生错误;
- 信号和槽的参数类型必须匹配,在Qt Designer中进行信号和槽编辑时定义槽函数时必须带参数类型;
- 由于Qt是C++语言的平台,信号的参数类型都是C++类型的,可能存在部分参数类型Python无法使用的情况,这种情况老猿在学习中遇到过但没记录下来,也没有专门研究,但绝大多数类型特别是标准的C++类型可以支持;
- Python没有指针以及引用类型,这两种信号带的参数在信号和槽函数编辑时槽函数参数必须是指针以及引用类型,但在派生类实现槽函数时将其当成去掉指针或引用的类型。例如,
QAbstractButton *类型在实现槽函数时应该作为QAbstractButton类型处理。
2.2、信号和槽是松耦合的
这种松耦合表现在发出信号的对象既不知道也不关心哪个槽接收信号,槽也不知道有哪些信号连接到它。从某种程度上讲,信号和槽是类似电视节目和观众之间的关系。电视节目播放类似于信号发射,观众观看节目类似于槽,观众选择自己感兴趣的节目观看就是建立信号与槽的连接。
2.3、信号和槽之间是多对多的关系
- 可将多个信号连接到同一个槽
- 可将同一个信号连接到多个槽
- 可以将一个信号直接连接到另一个信号(这将在第一个信号发出时立即发出第二个信号)
下图是官网文档给出的信号和槽的对应关系示例:

2.4、信号和槽支持预定义和自定义匹配
因Qt在其类库中预定义了很多信号和槽,因此在Qt中可以仅使用Qt类库中预定义的信号和槽,也可以只使用Qt类库中预定义的信号而使用自已的槽,也可以使用Qt类库中预定义的槽来响应自已定义的信号,当然,槽和信号也都可以使用自定义的( 关于自定义信号本节不进行进一步探讨)。
2.5、可以断开信号和槽之间的连接
在信号和槽连接之后,connect方法会返回一个QMetaObjec.Connection类型的连接句柄,通过该句柄调用 disconnect()就可以断开信号和槽的连接。
三、Qt Designer中信号和槽操作
3.1、概述
在Qt Designer中可以自定义信号,但本节只介绍使用已有信号的操作方法。
3.2、槽函数的定义
要定义一个新的槽方法,通过Edit->Edit Signals/Slots或F4快捷键进入信号和槽编辑界面,如图:

进入编辑界面后双击要新增槽函数的部件或者从发射信号的部件开始使用鼠标画连接线,线的终点为槽函数所在部件(一般在窗口对象),释放鼠标后调出配置界面,如图为从pushButton发出信号到窗口的槽函数建立连接的案例:

点击上图中蓝色标记的Edit按钮,如图:

点击上图中的加号就可以增加新的槽函数。
注意:
- 在此定义槽函数需要输入槽函数名和各参数类型,不能输入参数名
- 参数类型只能是C++的通用类型和Qt支持的类型,不能是Python独有的类型
- 对已有的自定义槽函数可以通过鼠标双击进行编辑
3.3、信号和槽函数连接方法1
进入信号和槽的编辑界面后,可以通过鼠标在编辑界面右侧的信号列表中选择对应信号,在槽函数列表中选择对应槽函数,点击OK保存退出,就完成了信号和槽函数的连接建立。如图:

注意:
- 上图黄色荧光笔标记部分,如果要选择Qt对应部件预定义的槽函数,必须对该选项进行勾选
- 在进行信号和槽编辑的时候,需要注意如果窗口使用了布局部件全被覆盖了窗口表面区域,可能导致无法使用本方法进行信号和槽的连接编辑,请参考:《PyQt(Python+Qt)学习随笔:Designer中不能编辑信号和槽的问题》
- 在Qt Designer中如果带不同参数的同名信号如clicked()和clicked(bool)信号连接到名字相同但参数不同的槽函数会导致二者最终会执行同一个槽函数,具体请参考:《PyQt(Python+Qt)学习随笔:clicked和clicked(bool)信号连接同名函数出现的问题》
3.4、信号和槽函数连接方法2
除了3.3部分介绍的信号和槽函数的连接方法之外,还可以在Designer右侧的信号和槽函数编辑界面进行信号和槽函数连接。如图黄色荧光笔标记窗口:

点击下面蓝色标记的加号,新增一条可以编辑记录,选择每个字段鼠标双击进行编辑,如图:

退出编辑状态后相关连接自动保存。
这种方式与第一种方式相比,有如下不同:
- 第一种方式直接使用连接线类似绘制线条一样操作,相比第二种方式操作简单、连接显示直观,但当界面线条过多杂乱时反而不如第二种方式操作方便
- 第二种方式可以将一些不可见的对象如Action对象在编辑界面进行操作,而第一种方式则不行
小结
本节详细介绍了Qt中信号和槽的概念,同时详细阐述了PyQt中与Qt中使用的一些差别,并详细介绍了Qt Designer中的操作方法,有助于大家深入理解信号和槽的概念,并熟练使用。

老猿Python,跟老猿学Python!
博文目录
博客地址
第15.16节 PyQt(Python+Qt)入门学习:PyQt中的信号(signal)和槽(slot)机制以及Designer中的使用的更多相关文章
- 第15.25节 PyQt(Python+Qt)入门学习:Model/View开发实战--使用QTableView展示Excel文件内容
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.概述 在前面的订阅专栏<第十九章.Model/View开发:QTableView的功能及属 ...
- 第15.33节 PyQt(Python+Qt)入门学习:containers容器类部件QTabWidget选项窗部件简介
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.概述 容器部件就是可以在部件内放置其他部件的部件,在Qt Designer中可以使用的容器部件有 ...
- 第15.31节 PyQt(Python+Qt)入门学习:containers容器类部件GroupBox分组框简介
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.概述 容器部件就是可以在部件内放置其他部件的部件,在Qt Designer中可以使用的容器部件有 ...
- 第15.29节 PyQt(Python+Qt)入门学习:containers容器类部件QScrollArea滚动区域详解
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.概述 Scroll Area提供了一个呈现在其他部件上的可滚动区域视图,滚动区域用于显示框架内的 ...
- 第15.28节 PyQt(Python+Qt)入门学习:Model/View架构中的便利类QTableWidget详解
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.引言 表格部件为应用程序提供标准的表格显示工具,在表格内可以管理基于行和列的数据项,表格中的最大 ...
- 第15.27节 PyQt(Python+Qt)入门学习:Model/View架构中的便利类QTreeWidget详解
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.引言 树部件(Tree Widget)是Qt Designer中 Item Widgets(It ...
- 第15.26节 PyQt(Python+Qt)入门学习:Model/View架构中的便利类QListWidget详解
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.概述 列表部件(List Widget)对应类QListWidget,是从QListView派生 ...
- 第15.24节 PyQt(Python+Qt)入门学习:Model/View架构中QTableView的作用及属性详解
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.概述 在Designer的部件栏Item Views中提供了PyQt和Qt已经实现好的table ...
- 第15.17节 PyQt(Python+Qt)入门学习:PyQt图形界面应用程序的事件捕获方法大全及对比分析
老猿Python博文目录 老猿Python博客地址 按照老猿规划的章节安排,信号和槽之后应该介绍事件,但事件在前面的随笔<PyQt(Python+Qt)实现的GUI图形界面应用程序的事件捕获方法 ...
随机推荐
- 用数组实现队列(顺序队列&循环队列)
用数组实现队列(顺序队列&循环队列) 顺序队列 ️ 队列(先进先出) 几个问题: 队列方法:入队.出队 队列的存储:即队首队尾两个指针, 扩容:如果队列容量不够了,应该扩容,如果队尾没有位置了 ...
- mysql实现当前行的值累加上一行的值
数据库钱包表有日期.收入.支出三个字段.用mysql语句计算每日余额,得如下结果 select m.*, @total :=@total + 收入 - 支出 as 钱包余额 ( select * fr ...
- 使用配置文件方式记录Python程序日志
开发者可以通过三种方式配置日志记录: 调用配置方法的Python代码显式创建记录器.处理程序和格式化程序. 创建日志配置文件并使用fileConfig() 函数读取. 创建配置信息字典并将其传递给di ...
- 浅析TCP协议---转载
https://cloud.tencent.com/developer/article/1150971 前言 说到TCP协议,相信大家都比较熟悉了,对于TCP协议总能说个一二三来,但是TCP协议又是一 ...
- 【webSokect】基于django Channels的简单实现
# settings.py: INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.con ...
- HotSpot的启动过程(配视频进行源码分析)
本文将详细介绍HotSpot的启动过程,启动过程涉及到的逻辑比较复杂,细节也比较多,为了让大家更快的了解这部分知识,我录制了对应的视频放到了B站上,大家可以参考. 第4节-HotSpot的启动过程 下 ...
- 10大排序算法——Java实现
算法与实现 选择排序 算法思想 从数组中选择最小元素,将它与数组的第一个元素交换位置.再从数组剩下的元素中选择出最小的元素,将它与数组的第二个元素交换位置.不断进行这样的操作,直到将整个数组排序. 动 ...
- docker搭建渗透环境并进行渗透测试
目录 docker简介 docker的安装 docker.centos7.windows10(博主宿主机系统)之间相互通信 -docker容器中下载weblogic12c(可以略过不看) docker ...
- js替换div里的内容
<!DOCTYPE html><html><head><meta charset="utf-8"><title>< ...
- api-hook,更轻量的接口测试工具
前言 在网站的开发过程中,接口联调和测试是至关重要的一环,其直接影响产品的核心价值,而目前也有许多技术方案和工具加持,让我们的开发测试工作更加便捷.接口作为数据传输的重要载体,数据格式和内容具有多样性 ...