第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图形界面应用程序的事件捕获方法 ...
随机推荐
- leetcode26:valid-palindrome
题目描述 判断题目给出的字符串是不是回文,仅考虑字符串中的字母字符和数字字符,并且忽略大小写 例如:"A man, a plan, a canal: Panama"是回文 &quo ...
- [MIT6.006] 10. Open Addressing, Cryptographic Hashing 开放定址,加密哈希
前几节课讲散列表的时候,我们需要用Chaining,链接法需要用到指针pointer,但有一种方法可以不要Chaining和指针,还能在发生冲突时,为产生冲突的关键字寻找下一个"空" ...
- 进程 PCB 进程挂起
7-1 进程定义 OS系统从只能跑一个程序到能跑多个.进程可以描述程序的执行过程. 进程:一个具有一定独立功能的程序在一个数据集合上的一次动态执行过程. 只有当一个程序被OS加载到内存中,cpu对其 ...
- Spring源码之@Configuration原理
总结 @Configuration注解的Bean,在BeanDefinition加载注册到IOC容器之后,进行postProcessBeanFactory处理时会进行CGLIB动态代理 将@Prope ...
- hibernate 基础知识
1.hibernate的配置文件,一般放在classpath的根目录下,默认命名为hibernate.cfg.xml,代码例子如下: <!DOCTYPE hibernate-configurat ...
- Javaweb项目页面实时显示后台处理结果
http://www.cnblogs.com/dong-xu/p/6701271.html 此博文甚好,项目参照博主代码可实现. 前端页面: <%@ page language="ja ...
- 小而精的 Docker 项目,为什么要使用 Docker? Docker 容器
前言 为什么要使用 Docker? Docker 容器的启动在秒级 Docker 对系统资源利用率高,一台主机上可以同时运行数千个 Docker 容器. Docker 基本不消耗系统资源,使得运行在 ...
- 我要进大厂之大数据ZooKeeper知识点(1)
01 让我们一起学大数据 老刘又回来啦!在实验室师兄师姐都找完工作之后,在结束各种科研工作之后,老刘现在也要为找工作而努力了,要开始大数据各个知识点的复习总结了.老刘会分享出自己的知识点总结,一是希望 ...
- CTF-WEB-HCTF 2018 Warmup
题目链接 攻防世界-Warmup 解题思路 [原题复现]HCTF 2018 Warmup(文件包含)
- Python3 Socket
Socket socket介绍 socket意为套接字,是应用层与传输层TCP/IP,UDP之间通信的中间软件抽象层,它是一组接口.使用时只需遵循socket的格式与规定去编程,让socket组织数据 ...