【Qt初识】信号槽(一):核心概念与 connect 的使用
欢迎文末添加好友交流,共同进步!
- 目录
- 一、信号和槽概念
- 1.1概述
- 1.2 本质
- 1.3 理解
- 二、信号和槽的使用
- 三、如何知道内置信号与槽有哪些 & 深入理解 connect
- 3.1 学会使用官方文档
- 3.2 connect参数类型解释
目录
一、信号和槽概念
1.1概述
我们之前在讲点击按钮的时候将文本内容切换功能的时候提到过信号和槽,,然后触发事件发出的通知叫信号(就比如点击按钮),用来接收信号执行功能的方法(执行文本内容切换的方法)就叫槽。
信号和槽都是 Qt 特有的消息传输机制,它能将相互独立的控件关联起来。比如,按钮和编辑框本身是两个独立控件,点击按钮并不会对编辑框造成任何影响。但我们可以借助信号和槽机制,把按钮和编辑框关联在一起,实现点击按钮切换编辑框文本内容的效果。
1.2 本质
- 信号:是由于用户对窗口或者控件进行了某些操作,导致窗口或控件产生了某个特定的事件,这时Qt对应的窗口类会发出某个信号,以此对用户的操作做出反应。因此,信号的本质就是事件!
- 槽(slot)就是对信号的响应函数。
1.3 理解
我们可以简单的举一个例子,当你回家的时候看着你的对象不开心,你做一点小事她就生气!你心里盘算了一下,为啥呢???从自己的脑海中搜索种种可能,心想自己也没干啥坏事啊!哦!突然你想要了一个你最可能的原因,原来是每个月女生都有那么几天,这时候就去乖乖的冲了一杯红糖水端给她!
从我们这个例子中我们可以发现:
- 信号源:对象
- 信号类型:不开心,生气
- 方式(槽):快去冲红糖水
通过这个例子我们是不是可以更好的理解这个信号与槽了呢!它的执行顺序就是先关联信号+槽,然后触发,这才是基本规则。接下来我们看看如何使用!
二、信号和槽的使用
使用的话我们需要用到一个连接函数,顾名思义connect,它是由QOBject(Qt中内置类的祖宗)提供的函数(含静态重载),且Qt中所提供的类都是有继承关系的!为什么?因为我们之前讲过的对象树。
我们来看看connect()函数原型:
connect(constQObject*sender,constchar*signal,constQObject*receiver,constchar*method,Qt::ConnectionType type=Qt::AutoConnection)sender:信号源(谁发送的信号)signal:信号类型(如鼠标移动、点击按钮、点击键盘等)信号处理方式
receiver:谁来处理(即对应的控件)method:如何处理(也就是我们设定的槽函数)
type = Qt::AutoConnection:通常是用来指定关联方式的,一般是默认不需要我们自己手动设置
我们来看个例子更好的了解一下!
#include"widget.h"#include"ui_widget.h"#include<QPushButton>Widget::Widget(QWidget*parent):QWidget(parent),ui(newUi::Widget){ui->setupUi(this);QPushButton*pushbutton=newQPushButton(this);pushbutton->setText("关闭窗口");connect(pushbutton,&QPushButton::clicked,this,&QWidget::close);}Widget::~Widget(){deleteui;}&QPushButton::clicked与&QWidget::close我们可以看到系统给了我们两个图标,其实这能够更加快速的帮助我们分辨出信号与槽函数!
- 如第一张图我所框出来的就是信号,有三个类似无线网络的弧度的那个
- 如第二张图我所框出来的就是槽函数,锯齿形状
先创建出一个按钮(控件)然后设置文本,然后把点击按钮这个信号和槽(关闭窗口)连接起来。信号源就是我们创建的按钮,信号类型就是点击这个按钮,处理方式就是关闭窗口。
此处的close是QWidget内置的槽函数。
三、如何知道内置信号与槽有哪些 & 深入理解 connect
接下来我们来解决两个很容易让初学者产生疑惑的问题!
3.1 学会使用官方文档
我们上面说了我们所实现的关闭窗口的函数close是一个内置函数,而且触发信号是点击按钮的clicked那这些我们是如何知道的呢?解决这个疑问的核心就是多看官方文档!不会的就去查询!
我们直接在搜索框输入我们想要了解的控件名称然后点击搜索,就可以看到如下:
但是当我们把此界面全部翻看后并没有找到clicked这个信号函数的说明,聪明的你想到了Qt中的对象树,他们是一层一层的继承关系,既然此处没有找到,我们去看看它的父类呢!父类没有呢?那就父类的父类去查找呗!!
然后继续在这个界面进行翻阅,果不其然,就找到了!找到后当我们想要查询详细信息的话直接点击它即可!
我们用ai解读一下(建议自己慢慢解读理解,看英语文档那不我们必备技能嘛)
所以我们可以发现查找信号的时候,重点就是关注信号的发送时机——比如进行了某操作,就产生了这个信号!
3.2 connect参数类型解释
我们会发现connect参数里面的信号类型与处理方法要求传入的都是const char*指针类型,而我们手动传入的明显是函数指针,毫无疑问这是不同的指针类型!
我们可以按住ctrl,然后鼠标点击clicked和close,就可以跳转到它们的函数定义。我们也发现他们的类型是和const char*明显是不一样的!
形参要求传入的指针类型与实参指针类型是不同的,这种情况在C++是绝对不允许出现的,因为函数的传参本质就是赋值,即根本不会允许两种不同的指针类型去相互赋值!
那么为什么在Qt中我们运行成功后,点击关闭窗口按钮,它依然能够成功的连接信号与槽,那为什么会出现这种情况呢?因为我们知道connect函数是QObject中的成员函数,由于Widget继承自QWidget,而QWidget继承自QObject类,所以我们在Widget中可以使用connect,并且我们去找connect也应该在文档中搜索QObject!!
找到然后点击它,我们就能跳转到相应的函数介绍。我们会发现如果要想将指针类型转换的话我们需
- 要使用**SIGNAL()**这个宏去修饰第二个参数
- 使用**SLOT()**这个修饰去包第四个参数
connect(pushbutton,SIGNAL(clicked()),this,SLOT(close()));经过宏的修饰之后,宏会将函数指针的类型转化为cong char*类型进行传参,也就是说我们的调用connect不需要指定是位于哪一个类中的成员函数,通过宏的修饰就将函数指针的类型转化为了const char*进行传参
其实这个官方文档是旧版本Qt的connect函数声明,以前的传参方法和现在的传参方法是有区别的,而我们从Qt5开始就做了简洁,不用再写宏,直接给connect提供了重载版本,第二个和第四个参数成了泛型参数,允许你传入任意类型的指针,并且带有一定的参数检查功能!
如果参数传入的不匹配会自动编译出错!如果我们传入的第二个参数的函数指针不是第一个参数指向的类的成员函数,或者传入的第四个参数的函数指针不是第三个参数指向的类的成员函数,就会发生错误!
就做了简洁,不用再写宏,直接给connect提供了重载版本,第二个和第四个参数成了泛型参数,允许你传入任意类型的指针,并且带有一定的参数检查功能!
如果参数传入的不匹配会自动编译出错!如果我们传入的第二个参数的函数指针不是第一个参数指向的类的成员函数,或者传入的第四个参数的函数指针不是第三个参数指向的类的成员函数,就会发生错误!