一、信号和槽概述
- 在Qt中,用户和控件每一次交互称为一次事件。比如按下一个按钮,每个事件都会发出一个信号,例如用户点击按钮会发出按钮被点击的信号
- Qt中的所有控件都具有接收信号的能力,一个控件可以接收多个信号。对每个信号控件都会作出相应的动作,这个动作就称之为槽
- 信号和槽是Qt特有的信息传输机制,它能将相互独立的控件关联起来

二、信号的本质
当用户对 Qt 的窗口或控件执行了某种操作时,会触发该窗口或控件产生对应的特定事件;此时,Qt 中对应的窗口类会向外发出一个特定的信号,以此来响应用户的这次操作。从这个角度来说,Qt 里信号的本质就是事件。
那么在 Qt 中,信号是以何种形式呈现给使用者的呢?
- 我们对哪个窗口进行操作,该窗口就能捕捉到这些被触发的事件。
- 对于使用者而言,触发一个事件后,我们就能接收到 Qt 框架为我们发出的某个特定信号。
- 信号的呈现形式是函数,也就是说当某个事件产生时,Qt 框架会调用对应的信号函数,以此通知使用者。
- 在 Qt 中,信号的发出者是某个已经完成实例化的类对象。
三、槽的本质
槽(Slot)就是对信号响应的函数。槽就是一个函数,与一般的 C++ 函数是一样的,可以定义在类的任何位置( public、protected 或 private ),可以具有任何参数,可以被重载,也可以被直接调用(但是不能有默认参数)。槽函数与一般的函数不同的是:槽函数可以与一个信号关联,当信号被发射时,关联的槽函数被自动执行。
说明
信号和槽机制底层是通过函数间的相互调用实现的。每个信号都可以用函数来表示,称为信号函数;每个槽也可以用函数表示,称为槽函数。例如: "按钮被按下" 这个信号可以用 clicked () 函数表示,"窗口关闭" 这个槽可以用 close () 函数表示,假如使用信号和槽机制 实现:"点击按钮会关闭窗口" 的功能,其实就是 clicked () 函数调用 close () 函数的效果。
信号函数和槽函数通常位于某个类中,和普通的成员函数相比,它们的特别之处在于:・信号函数用 signals 关键字修饰,槽函数用 public slots、protected slots 或者 private slots 修饰。signals 和 slots 是 Qt 在 C++ 的基础上扩展的关键字,专门用来指明信号函数和槽函数;信号函数只需要声明,不需要定义(实现),而槽函数需要定义(实现)。
四、信号和槽的使用
链接信号和槽
connect()
connect (const QObject *sender,const char * signal ,const QObject * receiver ,const char * method ,Qt::ConnectionType type = Qt::AutoConnection )
sender:信号的发送者
signal: 发送的信号
receiver: 信号的接收者
method: 接收信号的 槽函数
type: 用于指定关联方式,默认的关联方式为Qt::AutoConnection,通常不需要手动设定

五、查看内置信号和槽


通过Qt Create生成信号槽代码


按下之后,Qt会自动生成槽函数声明和定义
自动生成的槽函数的名称有一定的规则 满足on_XXX_sss(XXX 表示对像名, SSS表示信号名)
按照这种方式命名的槽函数就会被Qt自动关联


五、自定义信号和槽
5.1 基本语法
在 Qt 中,允许自定义信号的发送方以及接收方,即可以自定义信号函数和槽函数。但是对于自定义的信号函数和槽函数有一定的书写规范。
1、自定义信号函数书写规范
(1)自定义信号函数必须写到 "signals" 下;
(2)返回值为 void,只需要声明,不需要实现;
(3)可以有参数,也可以发生重载;
2、自定义槽函数书写规范
(1)早期的 Qt 版本要求槽函数必须写到 "public slots" 下,但是现在高级版本的 Qt 允许写到类的 "public" 作用域中或者全局下;
(2)返回值为 void,需要声明,也需要实现;
(3)可以有参数,可以发生重载;
3、发送信号
使用emit关键字发送信号。



六、带参数的信号和槽
Qt的信号和槽也支持带有参数,但是需要槽和信号的参数要对应
七、 信号和槽的链接方式
7.1 一对一
一个信号链接一个槽
一个信号对应一个信号
7.2 一对多
一个信号链接多个槽
多个信号链接一个槽函数
八、信号和槽的其他说明
8.1 信号和槽的断开
使用disconnect函数可以将信号和槽断开

8.2 Qt4版本信号和槽的链接
Qt4中的connect用法和Qt5相比是更复杂的需要搭配SIGAL 和 SLOT宏来完成,而且没有必要的类型检查

九、使用Lambda表达式定义槽函数
Lammbda表达式的语法格式如下
[ capture ] ( params ) opt -> ret { Function body;}

局部变量引入方式

由于使⽤引⽤⽅式捕获对象会有局部变量释放了⽽ Lambda 函数还没有被调⽤的情况。如果执⾏Lambda 函数,那么引⽤传递⽅式捕获进来的局部变量的值不可预知。所以绝⼤多数场合使⽤的形式为: [=] () { }・早期版本的 Qt,若要使⽤ Lambda 表达式,要在 ".pro" ⽂件中添加: CONFIG += C++11因为 Lambda 表达式 是 C++11 标准提出的。Qt5 以上的版本⽆需⼿动添加,在新建项⽬时会⾃动



