Qt之信号与槽

目录

基本概念 

信号与槽的使用

自定义信号和槽函数

1.通过代码来自定义槽函数

2.通过QtCreator生成信号槽代码

3.自定义信号

4. 带参数的信号与槽

5.意义 

6.信号与槽的断开

7.使⽤ Lambda 表达式定义槽函数 

小结


接下来的日子会顺顺利利,万事胜意,生活明朗-----------林辞忧

基本概念 

1.在 Qt 中,⽤⼾和控件的每次交互过程称为⼀个事件,每个事件都会发出⼀个信号, Qt 中的所有控件都具有接收信号的能⼒,⼀个控件还可以接收多个不同的信号。对于接收到的每个信号,控件都会做出相应的响应动作,在 Qt 中,对信号做出的响应动作就称之为槽。
2.信号的三个要素:
信号源:由哪个控件发出的信号
信号的类型:用户进行不同的操作,就可能触发不同的信号
信号的处理方式:槽,本质是函数, 槽函数可以与⼀个信号关联,当信号被 发射时,关联的槽函数被⾃动执⾏。在Qt中使用connect函数,把一个信号和槽关联起来,后续只要信号触发,Qt就会自动的执行槽函数,槽函数本质就是回调函数
3.信号函数和槽函数通常位于某个类中,和普通的成员函数相⽐,它们的特别之处在于:
  信号函数⽤ signals 关键字修饰,槽函数⽤ public slots、protected slots 或者 private slots 修
  饰。signals 和 slots 是 Qt 在 C++ 的基础上扩展的关键字,专⻔⽤来指明信号函数和槽函数;
4.信号函数只需要声明,不需要定义(实现),⽽槽函数需要定义(实现)
5. 信号函数的定义是 Qt ⾃动在编译程序之前⽣成的. 编写 Qt 应⽤程序的程序猿⽆需关注.
这种⾃动⽣成代码的机制称为 元编程

信号与槽的使用

1.在Qt中一定是先关联信号与槽,然后再触发这个信号,顺序不能颠倒,否则信号就不知道如何处理了

2.connect函数是QObject这个类提供的静态成员函数

3.Qt中提供的类,本身是存在一定的继承关系的,Qt 中提供的很多类都是直接或者间接继承⾃ QObject

4.connect() 函数原型:

5.举例: 在窗⼝中设置⼀个按钮,当点击 "按钮" 时关闭 "窗⼝" ,针对button点击,Widget就会关闭
一些注意点:

在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.查看内置的信号与槽

系统⾃带的信号和槽通常是通过 "Qt 帮助⽂档" 来查询,寻找关键字 signals来查询信号

自定义信号和槽函数

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 

小结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值