目录

接下来的日子会顺顺利利,万事胜意,生活明朗-----------林辞忧
基本概念
信号与槽的使用
1.在Qt中一定是先关联信号与槽,然后再触发这个信号,顺序不能颠倒,否则信号就不知道如何处理了
2.connect函数是QObject这个类提供的静态成员函数
3.Qt中提供的类,本身是存在一定的继承关系的,Qt 中提供的很多类都是直接或者间接继承⾃ QObject

4.connect() 函数原型:

在connect函数原型当中,第1和第3个参数的类型都是QObject*,而这里一个是QPushButton*和Widget*,在上面就提到Qt中提供的类都是直接或间接继承QObject类的,所以根据c++继承中父子类的切片规则,子类对象是可以直接传给父类对象的
对于第2和第4个参数的类型都是函数指针,而原型中都是char*,此时根据常识这两个类型的传递是不匹配的,因此这里采用了转化的机制

先查看官方文档中对connect的声明
这个是旧版本的connect的实现,此时给信号参数传参,要搭配一个SIGNAL宏,给槽函数传参要搭配一个SLOT宏来实现函数指针转为char*
但经过后来重载改变后,在文档这里是查看不出啥的,这样就需要在代码中点击connect,再按Ctrl+鼠标左键,查看connect函数的实现

在重载版本当中,就不需要写SIGNAL和SLOT宏了,而是将第2和第4个参数变为了泛型参数,允许传入任意类型的函数指针

6.查看内置的信号与槽
自定义信号和槽函数
1.通过代码来自定义槽函数

2.通过QtCreator生成信号槽代码
先用PushButton控件来创建一个窗口,再点击右键转换到槽

双击之后就转换到这里
在这里QtCreator直接生成好了一个函数
在执行过程中,这个函数会调用connectSlotsByName函数
3.自定义信号

(1)Widget类继承了QWidget和QObject类,这两个类中已经提供了一些信号了,可以直接使用
(2)Qt中的信号是一类非常特殊的函数
( 3)我们自己定义的信号,只需要写出函数声明,并且告诉Qt这是一个信号。而函数的定义,是Qt在编译的过程中自动生成的
(4)作为信号函数,这个函数的返回值必须是void,有没有参数都可以,还支持重载
(5)在写信号函数声明时,必须添加Qt关键字signals。在qmake的时候,调用一些代码的分析/生成工具,在扫描到类中包含signals关键字时,就会自动的把下面的函数声明认为是信号,并且自动的给这些信号函数生成对应的定义

在建立连接之后,必须要发射信号,Qt内置的信号是不需要自己通过代码手动来触发的,用户在GUI进行某些操作时,就会自动触发对应的信号(发射信号的代码已经内置在Qt框架中了)
先后执行顺序

4. 带参数的信号与槽
(1)当信号带有参数的时候,槽的参数必须和信号的参数一致。此时发射信号的时候,就可以给信号函数传递实参,与之对应的这个参数就会被传递到对应的槽函数当中
这里的一致是参数类型要一致,个数可以不一致,不一致的时候要求信号的参数的个数必须要比槽的参数个数要多

(2) 信号函数的参数个数只要>=槽函数的参数个数,就可以正常使用,否则就会编译报错
这是为啥允许信号参数个数比槽函数的多呢? 一个槽函数可能会绑定多个信号,如果我们严格要求参数个数一致,就意味着信号绑定到槽的要求变高了,换言之,当下的这种规则,信号与槽之间的绑定就更加灵活了,更多的信号就可以绑定到槽函数上了
当个数不一致时,槽函数就会按照参数顺序,拿到信号的前N个参数,这样就至少确保槽函数的每个参数都是有值的
(3)Q_OBJECT宏

这个宏展开会得到一系列的复杂代码,会涉及到Qt的实现。如果不加这个宏,就会编译报错
5.意义
所谓的信号槽本质就是要响应用户的操作
(1)解耦合,把触发用户操作的控件和处理对应用户的操作逻辑解耦合
(2)实现多对多的效果。一个信号可以connect到多个槽函数上;一个槽函数也可以被多个信号connect.但在实际的开发过程中很多都是用到一对一的(一个事件只能对应一个处理函数)
6.信号与槽的断开
使用disconnect来断开信号槽的连接。disconnect 的⽤法和 connect 基本⼀致。主动断开往往是把信号连接到另一个槽函数上

7.使⽤ Lambda 表达式定义槽函数
(1)lambda表达式本质是一个回调函数,一次性使用,无法直接获取上层作用域的变量,为了解决这个问题,引入了变量捕获语法,通过变量捕获,获取到外层作用域中的变量

也可以写为
写作[=]的含义就是把上层作用域中所有的变量名给捕获进来

(2)早期版本的 Qt,若要使⽤Lambda表达式,要在 ".pro" ⽂件中添加: CONFIG += C++11
小结


1801

被折叠的 条评论
为什么被折叠?



