Qt之信号与槽

目录

基本概念

信号与槽的使用

自定义信号和槽函数

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

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

3.自定义信号

[4. 带参数的信号与槽](#4. 带参数的信号与槽)

5.意义

6.信号与槽的断开

[7.使⽤ Lambda 表达式定义槽函数](#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

小结

相关推荐
锦亦之22339 小时前
QT+OSG+OSG-earth如何在窗口显示一个地球
开发语言·qt
柳鲲鹏13 小时前
编译成功!QT/6.7.2/Creator编译Windows64 MySQL驱动(MinGW版)
开发语言·qt·mysql
三玖诶13 小时前
如何在 Qt 的 QListWidget 中逐行添加和显示数据
开发语言·qt
阳光开朗_大男孩儿19 小时前
DBUS属性原理
linux·服务器·前端·数据库·qt
Alphapeople20 小时前
Qt Modbus
开发语言·qt
竹林海中敲代码20 小时前
Qt Creator 集成开发环境 常见问题
qt·qt工具常见问题
竹林海中敲代码1 天前
Qt安卓开发连接手机调试(红米K60为例)
android·qt·智能手机
长沙红胖子Qt1 天前
关于 Qt运行加载内存较大崩溃添加扩大运行内存 的解决方法
开发语言·qt·qt扩大运行内存
gopher95111 天前
qt相关面试题
开发语言·qt·面试
三玖诶1 天前
在 Qt 中使用 QLabel 设置 GIF 动态背景
开发语言·qt·命令模式