一、信号与槽(Signal & Slot)的基本概念
1、了解信号与槽
(1)信号(Signal):在特定情况下被发射的事件,例如PushButton 最常见的信号就是鼠标单击时发射的 clicked() 信号;
(2)槽(Slot):对信号响应的函数。槽就是一个函数,与一般的C++函数是一样的,可以定义在类的任何部分(public、private 或 protected),可以具有任何参数,也可以被直接调用。
信号与槽,实现了对象与对象之间的通信,一个对象发生了改变就会发送信号通知另外一个对象,另外一个对象收到信号就会执行一个函数,这个函数我们称为槽。简单地说,就是“发布-订阅者”模式。
要实现信号与槽函数的绑定,我们需要做以下几步。
(1)头文件中声明这个槽函数;
(2)在.cpp文件中定义这个槽函数,也就是把需要做什么事这个活动内容写下来;
(3)在.cpp文件中的构造函数里面连接信号与槽,用connect()函数。
2、信号与槽的自动绑定
(除了用connect()函数,信号与槽也可以自动连接,不需要connect(),但是槽函数名需要设置成,举例:on_函数名_clicked)
比如,在设计的ui界面上,将鼠标放置于pushButton上面,点击右键,选项“转到槽...”。
此时会出现如下窗口,若是选择按钮单击有效则选择click(),然后点击OK。此时将会自动生成如下函数:
void Dialog::on_MyButton_clicked()
{
//添加自己的业务逻辑
}
3、信号与槽的手工绑定
(1)信号的声明
signals:
void mysignal_1();
void mysignal_2(int data);
QT自带很多控件,这些控件本身就定义了很多信号,比如button的clicked(), pressed()等。
(2)槽的声明
public slots:
void myslot_1();
void myslot_2(int data);
(3)信号与槽的绑定
connect(sender, SIGNAL(signals), receiver, SLOT(slot));
(4)发射信号
emit mySignal_1(); // 发射信号mySignal_1
(5)信号和槽的连接规则
(5.1)信号参数可以比槽函数多,反之则不可以
(5.2)一个信号可以连接多个槽
(5.3)多个信号可以连接到一个槽
(5.4)一个信号可以与另一个信号连接
二、例子
用Qt Creator创建一个project。
1、mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
int a = 0;
signals: //声明信号
void mySignal_1();
void mySignal_2(int data);
public slots: //声明槽函数
void mySlot_1();
void mySlot_2(int data);
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
2、mainwindow.cpp
#include <QDebug>
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->pushButton->setText("Hello World");
//信号与槽的连接
connect(this, SIGNAL(mySignal_1()), this, SLOT(mySlot_1()));
connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(mySlot_1()));
//发射信号
emit mySignal_1();
}
MainWindow::~MainWindow()
{
delete ui;
}
//槽函数的实现
void MainWindow::mySlot_1(){
qDebug() << "call mySlot_1()";
emit mySignal_2(10000);
}
//槽函数的实现(统计按下按钮次数,并在输出显示中输出)
void MainWindow::mySlot_2(int data){
qDebug() << "call mySlot_2(), data:" << data;
a++;
qDebug() << "第" << a << "次按下按钮";
}
//这个pushButton_clicked方法,直接在ui界面右键转到槽就可以自动生成
void MainWindow::on_pushButton_clicked(){
qDebug() << "on_pushButton_clicked()";
}
3、执行结果:
(1)程序启动后,会输出:call mySlot_1()
(2)当点击按钮后,输出如下:
(3)下面我把signal_2和slot_2关联起来(connect中只有类型 - 比如int,没有参数)
connect(this, SIGNAL(mySignal_2(int)), this, SLOT(mySlot_2(int)));
执行结果如下:
参考:
(1)Qt Creator:初识信号与槽
(2)Qt6教程之三(13) TCP/IP通讯与socket编程