目录
我们先用通熟的例子来说一下:
比如,你是你个孩子的爸爸或者妈妈,你的孩子放学回到家之后,先是给你倒茶又是捏腿的,此是你就想是不是考试没考好,还是在学校犯错误了。
信号源:你的孩子
信号类型:非常热情
信号处理方式:脑子里搜索各种可能,是不是考试没考好,还是在学校犯错误了,最终得出一个结果,没考好=》先教育批评,然后鼓励下。
上述操作过程中,都是提前把不同的信号处理方式,提前准备好的。
一定是先把信号的处理方式准备好,在触发信号。
Qt中一定是先关联好 信号和槽 顺序不能颠倒。
信号和槽概述
在 Qt 中,用户和控件的每次交互过程称为⼀个事件。⽐如 "用户点击按钮" 是⼀个事件,"用户关闭窗⼝" 也是⼀个事件。每个事件都会发出⼀个信号,例如用户点击按钮会发出 "按钮被点击" 的信号,用户关闭窗⼝会发出 "窗⼝被关闭" 的信号。
Qt 中的所有控件都具有接收信号的能力,⼀个控件还可以接收多个不同的信号。对于接收到的每个信号,控件都会做出相应的响应动作。例如,按钮所在的窗口接收到 "按钮被点击" 的信号后,会做出"关闭自己" 的响应动作;再比如输⼊框自己接收到 "输⼊框被点击" 的信号后,会做出 "显示闪烁的光标,等待用户输⼊数据" 的响应动作。在 Qt 中,对信号做出的响应动作就称之为槽。
信号和槽是 Qt 特有的消息传输机制,它能将相互独立的控件关联起来。⽐如,"按钮" 和 "窗口"
本身是两个独⽴的控件,点击 "按钮" 并不会对 "窗口" 造成任何影响。通过信号和槽机制,可以将 "按钮" 和 "窗口" 关联起来,实现 "点击按钮会使窗口关闭" 的效果。

信号的本质
- 信号是由于用户对窗口或控件进行了某些操作,导致窗口或控件产生了某个特定事件,这时Qt对应的窗口类会发出某个信号,以此对用户的操作做出反应。因此,信号的本质就是事件。如:
- 按钮单击、双击
窗口刷新
鼠标移动、
鼠标按下、鼠标释放
键盘输入
那么在 Qt 中信号是通过什么形式呈现给使用者的呢?
我们对哪个窗口进行操作,哪个窗口就可以捕捉到这些被触发的事件。
对于使用者来说触发了一个事件我们就可以得到 Ot 框架给我们发出的某个特定信号。
信号的呈现形式就是函数,也就是说某个事件产生了,Qt框架就会调用某个对应的信号函数,通知使用者。
在 Qt 中信号的发出者是某个实例化的类对象。
槽的本质
槽(Slot)就是对信号响应的函数。槽就是⼀个函数,与⼀般的 C++ 函数是⼀样的,可以定义在
类的任何位置( public、protected 或 private ),可以具有任何参数,可以被重载,也可以被直接调用(但是不能有默认参数)。槽函数与⼀般的函数不同的是:槽函数可以与⼀个信号关联,当信号被 发射时,关联的槽函数被自动执行。
说明
(1)信号和槽机制底层是通过函数间的相互调⽤实现的。每个信号都可以用函数来表示,称为信号函 数;每个槽也可以⽤函数表示,称为槽函数。例如: "按钮被按下" 这个信号可以⽤ clicked() 函数表示,"窗⼝关闭" 这个槽可以⽤ close() 函数表示,假如使⽤信号和槽机制- 实现:"点击按钮会关闭窗⼝" 的功能,其实就是 clicked() 函数调⽤ close() 函数的效果。
(2)信号函数和槽函数通常位于某个类中,和普通的成员函数相⽐,它们的特别之处在于:
信号函数⽤ signals 关键字修饰,槽函数⽤ public slots、protected slots 或者 private slots 修
饰。signals 和 slots 是 Qt 在 C++ 的基础上扩展的关键字,专门用来指明信号函数和槽函数;
信号函数只需要声明,不需要定义(实现),而槽函数需要定义(实现)。
信号和槽的使用
连接信号和槽
在 Qt 中,QObject 类提供了⼀个静态成员函数 connect() ,该函数专门用来关联指定的信号函数和槽函数。
connect() 函数原型
cpp
connect (const QObject *sender,
const char * signal ,
const QObject * receiver ,
const char * method ,
Qt::ConnectionType type = Qt::AutoConnection )//最后一个先不考虑基本用不到
参数说明:
- sender:信号的发送者;
- signal:发送的信号(信号函数);
- receiver:信号的接收者;
- method:接收信号的槽函数;
- type: ⽤于指定关联方式,默认的关联方式为 Qt::AutoConnection,通常不需要手动设定。
关闭窗口按钮

cpp
{
ui->setupUi(this);
QPushButton *btn = new QPushButton(this);
btn->setText("关闭");
btn->move(200,200);
connect(btn,&QPushButton::clicked,this,&Widget::close);
}
注意connect的第二个参数是clicked不是click

上面的那个代码至少还有两个重要的问题!!!!
1.你咋知道QPushButton有个clicked信号
2.你咋知道WIdget有close
唯一的答案就是多看文档:
如果我们在QPushButton找不到Clicked那我们可以去他的父类去看看,终会找到的。


同学们有没有发现一个问题:


这个函数声明是以前旧版本的Qt的connect函数声明
以前版本中,传参的写法和现在的其实也有区别的
connect(button,SIGNAL(&QPushButton::clicked),this,SLOT(&Widget::close));
Qt5开始,对上述写法做出来简化,不要再写SIGNAL和SLOT宏了
给connect提供了 重载版本,冲在版本中第二个和第四个参数形成了泛型参数,允许咱传如任意类型的函数指针了

自定义槽
第一种自定义槽
下面看一个例子:

现在.h文件中写:
cpp
void handle();
接下俩在.cpp文件中写入:
cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QPushButton*button = new QPushButton(this);
button->setText("按钮");
button->move(100,100);
connect(button,&QPushButton::clicked,this,&Widget::handle);
}
Widget::~Widget()
{
delete ui;
}
void Widget::handle()
{
//按下按钮 修改标题
this->setWindowTitle("按钮已经按下");
}
第二种定义槽
1.先拖入一个QPushButton

2.右键点击选择转到槽

3.点击clicked

4.点击clicked会自动生成一个段函数,我们直接写入


自定义信号(比较少见)
声明文件


总结:emit 发送信号
带参数的槽函数
信号的个数少于槽函数的个数
个数相同时


信号的个数大于槽的个数


当槽大于信号的个数

总结:槽的个数一定不能多于信号的个数
信号与槽的连接方式
一对一
主要有两种形式,分别是:⼀个信号连接⼀个槽 和 ⼀个信号连接⼀个信号。
(1)⼀个信号连接⼀个槽
在 "widget.h" 中声明信号和槽以及信号发射函数
在 "widget.cpp" 中实现槽函数,信号发射函数以及连接信号和槽;
(2)⼀个信号连接另⼀个信号


⼀对多
⼀个信号连接多个槽
(1)在 "widget.h" 头⽂件中声明⼀个信号和三个槽;
(2)在 "widget.cpp" ⽂件中实现槽函数以及连接信号和槽;
多对⼀
多个信号连接⼀个槽函数
(1)在 "widget.h" 头⽂件中声明两个信号以及⼀个槽;
(2)在 "widget.cpp" ⽂件中实现槽函数以及连接信号和槽;
信号与槽的断开(用得少)
使⽤ disconnect 即可完成断开.
disconnect 的⽤法和 connect 基本⼀致