槽的本质:对信号响应的函数。
 信号函数和槽函数通常位于某个类中,和普通的成员函数相⽐,它们的特别之处在于:  
 
信号函数⽤ signals 关键字修饰,槽函数⽤ public slots、protected slots 或者 private slots 修饰。signals 和 slots 是 Qt 在 C++ 的基础上扩展的关键字,专⻔⽤来指明信号函数和槽数;信号函数只需要声明,不需要定义(实现),⽽槽函数需要定义(实现)。
信号和槽的使用
 在 Qt 中,QObject 类提供了⼀个静态成员函数 connect() ,该函数专⻔⽤来关联指定的信号函数和槽函数。  
 
connect函数原型:
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,通常不需要⼿动设定。
自动生成槽函数
通过在UI中创建控件,鼠标右键(找到 【转到槽】-> 【选择对应的信号】)来快速生成槽函数。
该方法对应的操作如下:
 (1)  在 "widget.h" 头⽂件中⾃动添加槽函数的声明; 
 
 说明:  
  ⾃动⽣成槽函数的名称有⼀定的规则。槽函数的命名规则为:on_XXX_SSS,其中:  
 1、以 " on " 开头,中间使⽤下划线连接起来;2、" XXX " 表⽰的是对象名(控件的 objectName 属性)。3、" SSS " 表⽰的是对应的信号。如:" on_pushButton_clicked() " ,pushButton 代表的是对象名,clicked 是对应的信号。
(2) 在 "widget.cpp" 中⾃动⽣成槽函数定义.
自定义信号和槽
 1、⾃定义信号函数书写规范  
 
(1)⾃定义信号函数必须写到 "signals" 下;(2)返回值为 void,只需要声明,不需要实现;(3)可以有参数,也可以发⽣重载;
 2、⾃定义槽函数书写规范  
 
(1)早期的 Qt 版本要求槽函数必须写到 "public slots" 下,但是现在⾼级版本的 Qt 允许写到类的 "public" 作⽤域中或者全局下;(2)返回值为 void,需要声明,也需要实现;(3)可以有参数,可以发⽣重载;
带参数的信号和槽
 Qt 的信号和槽也⽀持带有参数, 同时也可以⽀持重载.  
 
 此处我们要求, 信号函数的参数列表要和对应连接的槽函数参数列表⼀致.  
 
 此时信号触发, 调⽤到槽函数的时候, 信号函数中的实参就能够被传递到槽函数的形参当中.  
 
 
 代码示例 
 
 widget.h 
 
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();signals:void mySignal(const QString& text,const QString& text2);public:void handleSignal(const QString& text);private slots:void on_pushButton_clicked();void on_pushButton_2_clicked();private:Ui::Widget *ui;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);connect(this,&Widget::mySignal,this,&Widget::handleSignal);//    // 发射出自定义的信号
//    //发送信号的操作,也可以在任意合适的代码中,不一定非得在构造函数里
//    emit mySignal();
}Widget::~Widget()
{delete ui;
}void Widget::handleSignal(const QString& text)
{
//    this->setWindowTitle("处理自定义信号");this->setWindowTitle(text);
}void Widget::on_pushButton_clicked()
{// 发射出自定义的信号//发送信号的操作,也可以在任意合适的代码中,不一定非得在构造函数里
//    emit mySignal();emit mySignal("把标题设置为标题1","");
}void Widget::on_pushButton_2_clicked()
{emit mySignal("把标题设置为标题2","");
}结果演示:

信号与槽的连接方式
一对一

一对多

多对一

代码演示(一对多,多对一)
widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();signals:void mySignal1();void mySignal2();void mySignal3();public slots:void mySlot1();void mySlot2();void mySlot3();private:Ui::Widget *ui;
};
#endif // WIDGET_Hwidget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);connect(this,&Widget::mySignal1,this,&Widget::mySlot1);connect(this,&Widget::mySignal1,this,&Widget::mySlot2);connect(this,&Widget::mySignal2,this,&Widget::mySlot1);connect(this,&Widget::mySignal2,this,&Widget::mySlot3);
}Widget::~Widget()
{delete ui;
}void Widget::mySlot1()
{qDebug()<<"mySlot1";
}void Widget::mySlot2()
{qDebug()<<"mySlot2";
}void Widget::mySlot3()
{qDebug()<<"mySlot3";
}信号与槽的断开
 使⽤ disconnect 即可完成断开.  
 
 disconnect 的⽤法和 connect 基本⼀致 
 
 代码演示 
 
 widget.h 
 
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();void handleClick();void handleClick2();//private slots:
//    void on_pushButton_clicked();private slots:void on_pushButton_2_clicked();private:Ui::Widget *ui;
};
#endif // WIDGET_Hwidget.hpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);connect(ui->pushButton,&QPushButton::clicked,this,&Widget::handleClick);
}Widget::~Widget()
{delete ui;
}void Widget::handleClick()
{this->setWindowTitle("修改窗口的标题");qDebug()<<"handleClick";
}void Widget::handleClick2()
{this->setWindowTitle("修改窗口的标题2");qDebug()<<"handleClick2";
}//void Widget::on_pushButton_clicked()
//{//}void Widget::on_pushButton_2_clicked()
{//先断开 pushButton 原来的信号槽disconnect(ui->pushButton,&QPushButton::clicked,this,&Widget::handleClick);
//    connect(ui->pushButton,&QPushButton::clicked,this,&Widget::handleClick2);
}使用lambda定义槽函数
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <QDebug>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QPushButton* button=new QPushButton(this);button->setText("按钮");button->move(200,200);connect(button,&QPushButton::clicked,this,[=](){qDebug()<<"lambda 被执行了!";button->move(300,300);this->move(100,100);});
}Widget::~Widget()
{delete ui;
}