Qt中的信号与槽及其自定义

信号源:哪个控件发的信号

信号的类型:用户进行不同的操作就会触发不同的信号

如点击按钮,在输入框移动光标,勾选一个复选框,选 择一个下拉框

信号的处理方式:槽(slot)----也就是函数,Qt中用connet函数将信号与槽关联起来,后续只要信号触发了,Qt就会自动执行槽函数

-----所谓的槽函数,本质也是一种回调函数

Qt中一定是先关联信号和槽,任何再触发整个信号,顺序不能颠倒,否则信号触发时,调用槽就会失败

connect函数

是QObject类提供的静态的成员函数

Qt提供的类本身存在一定的继承关系,QObject是其它Qt内置类的父类,而所有控件都是Qt的内置类,都继承与QObject,因此都能使用connect(如QPushButton是QAbstractButtond的子类,QAbstractButton是QWidget的子类,QWidget又是QObject的子类

函数原型:

connect(const QObject* sender,

const char* signal,

const QObject* receiver,

const char* method ,

Qt::ConnectionType type = Qt::AutoConnection)

最后一个参数是默认参数,可以无需传参

sender表示信号源,表示是哪个控件发出信号

signal表示信号类型

receiver表示由哪个控件负责接收信号

method表示如何对信号进行处理---接收信号的槽函数

为什么传入的实参是函数指针类型,但是形参类型是char * 类型,他们是同一种类型吗?

一种是char* ,一种是void (*)(); 但是为什么他们能匹配呢?

c++中不允许使用两个不同的指针类型相互赋值

此处之所以不报错是因为文档查到的是以前旧版本的内容,

而现在接收槽,类型是一个泛型参数----Qt封装的类型萃取

实例:

创建一个按钮,当用户进行点击时,就会关闭窗口

先引入头文件,创建按钮,插入对象树,设置文本,移动位置

进行信号绑定时,绑定click而不是clicked

click是一个slot函数,作用就是在调用时相当于点击了一次按钮

而clicked是点击后发出的点击信号

Widget继承于QWidget,close是QWidget的槽函数,同样被Widget继承,可以直接在Widget中使用,作用是关闭当前窗口/控件

通过点击QPushButton控件,关闭Widget窗口

但是为什么点击QPushButton控件就会发生clicked信号?

通过Qt Assistant进行查看

在父类的signal中就可以找到clicked

查看信号时,最关注的就是信号的发送时机

自定义槽函数

槽---slot,就是一个普通的成员函数

在cpp文件中进行按钮的定义,插入对象树,设置内容,定义槽函数,在h文件中声明槽函数

借助ui界面,Qt Designer进行自定义槽函数

拖出一个按钮

右键点击按钮,选择转到槽

选中clicked点击ok后,直接跳转到槽定义函数

无需进行connect链接,而是由Qt Creator直接生成

可以正常调用

Qt中除了通过connect的方式链接信号和槽,还能函数名来链接信号和槽

如: void Widget::on_pushButton_clicked()

pushButton是发送信号的控件,clicked是信号类型,若函数名符号以上格式,则Qt自动连接信号和槽-----connectSlotsByName

如果通过图形化界面创建控件,就可以使用这种函数名连接信号槽的方式定义槽函数

如果通过代码创建控件,需要手动connect,因为代码中无connectSlotsByName函数

自定义信号

自定义信号比较少见,实际开发中很少需要自定义信号

因为Qt内置的信号,基本上已经覆盖了所有可能的用户操作

所谓Qt的信号,本质上也就是一个"函数"

在Qt5及更高版本中,槽函数和普通成员函数之间基本无区别

但是信号是一类非常特殊的函数

只需要写成函数声明,并告诉Qt这是一个"信号"即可

这个函数的定义,是在Qt编译过程中自动生成的

作为信号函数,返回值必须是void,有无参数都行,支持重载

在h文件中声明信号和槽

signals是Qt自己扩展的关键字

qmake时,调用工具自动生成相关定义

在cpp文件中进行连接和槽函数定义

但是运行之后,槽函数未被调用,因为尽管连接了信号和槽,但是没有发出信号

如何触发自定义的信号?

Qt内置信号时用户在ui界面进行某些操作时,自动触发对象信号

自定义信号需要通过代码手动发送---emit

也可以通过控件,将其槽函数设置为发送自定义信号,通过如点击按钮的方式调用槽函数,发送自定义信号

实际上emit无作用,只写一个mySignal也能发送信号,发送信号的操作包含在mySignal内部生成的函数定义中了

带参数的信号和槽

信号和槽也可以带参数,当信号带参数时,槽的参数必须和信号的参数一致

发送信号时,就可以给信号传递实参,将参数传递到对于的槽p,实现让信号给槽传参

在h文件中给自定义信号和槽函数声明带参数:

要求参数类型一致,,信号的参数个数必须要比槽的参数个数更多

发送带参数的信号,将参数传递给槽函数

槽函数接收参数后进行使用

可以通过给发送的信号传递不同的参数,调用同一个槽函数实现不同的效果

为什么允许信号的参数比槽的参数多?

一个槽函数可能绑定多个信号,若要求信号与槽参数必须一致,则槽和信号就变为一对一关系

如果槽和信号参数不一致,槽函数就会按照参数顺序,拿到信号的前n个参数

Qt中如果要让某个类实现信号槽,则可以在类中定义信号和槽函数,必须要在类最开始的地方,写Q_OBJECT宏,如果不加这个宏,编译时会报错

信号槽的意义

用于响应用户的操作

实现解耦合:把触发用户操作的控件和处理对于用户操作逻辑解耦合

实现多对多:一个信号可以connect到多个槽函数上,一个槽函数也可以被多个信号connect

断开信号和槽的连接

disconnect,使用方法和connect几乎一致

使用lambda表达式---语法糖定义槽函数

lambad本质是一个匿名函数,注意应用在"回调函数"场景中

如:

但是在lambda表达式中无法找到button控件,因为lambda表达式本质是一个回调函数,是无法直接获取到上层作用域中的变量

lambda引入"变量捕获"来解决无法获取上层作用域变量的问题

如:

需要注意的是,lambda表达式本质是回调函数,其内变量的生命周期特殊,由于此处button是new出的变量,声明周期跟随整个窗口,可以随时使用

相关推荐
qq_537562677 分钟前
跨语言调用C++接口
开发语言·c++·算法
wjs202417 分钟前
DOM CDATA
开发语言
Tingjct19 分钟前
【初阶数据结构-二叉树】
c语言·开发语言·数据结构·算法
猷咪1 小时前
C++基础
开发语言·c++
IT·小灰灰1 小时前
30行PHP,利用硅基流动API,网页客服瞬间上线
开发语言·人工智能·aigc·php
快点好好学习吧1 小时前
phpize 依赖 php-config 获取 PHP 信息的庖丁解牛
android·开发语言·php
秦老师Q1 小时前
php入门教程(超详细,一篇就够了!!!)
开发语言·mysql·php·db
烟锁池塘柳01 小时前
解决Google Scholar “We‘re sorry... but your computer or network may be sending automated queries.”的问题
开发语言
是誰萆微了承諾1 小时前
php 对接deepseek
android·开发语言·php
2601_949868361 小时前
Flutter for OpenHarmony 电子合同签署App实战 - 已签合同实现
java·开发语言·flutter