一、简介
信号与槽(Signal & Slot)是 Qt 最核心、最独特的特性,本质是一种解耦的事件通信机制—— 用于对象之间的交互(如按钮点击触发函数执行、数据传递),无需对象之间直接依赖,比传统回调函数更灵活、安全。
二、核心概念
信号(Signal):对象发出的 “事件通知”(如按钮被点击 clicked()、文本框内容变化 textChanged()),仅需声明,无需手动实现(Qt 元对象编译器 moc 自动生成);
槽(Slot):接收信号并处理的 “响应函数”(如按钮点击后执行 onBtnClicked()),需声明并实现,支持普通成员函数、Lambda 表达式;
连接(Connect):通过 QObject::connect() 建立信号与槽的关联,告诉 Qt “哪个信号触发哪个槽”;
发射(Emit):通过 emit 关键字触发信号(可省略,但建议写,提高可读性),信号发射后,所有绑定的槽函数会自动执行。
三、信号与槽的使用前提(必须满足)
类必须继承 QObject:信号槽依赖 Qt 元对象系统(moc),只有 QObject 子类才能使用;
类中必须包含 Q_OBJECT 宏:触发 moc 生成信号槽相关代码(如信号的实现、槽函数注册);
.pro 项目文件需启用 Qt 核心模块:至少包含 QT += core(信号槽核心依赖),UI 项目需加 gui widgets;
Qt 版本支持:Qt 5+ 推荐用 “函数指针语法”(类型安全),Qt 4 及之前用 “字符串语法”(已过时)。
四、代码示例

mywidget.h
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QMainWindow>
#include "teacher.h"
#include "student.h"
QT_BEGIN_NAMESPACE
namespace Ui {
class MyWidget;
}
QT_END_NAMESPACE
class MyWidget : public QMainWindow
{
Q_OBJECT
public:
MyWidget(QWidget *parent = nullptr);
~MyWidget();
void sendTo();
//
private:
Ui::MyWidget *ui;
Teacher *t1;
Student *s1;
};
#endif // MYWIDGET_H
student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <QObject>
class Student : public QObject
{
Q_OBJECT
public:
explicit Student(QObject *parent = nullptr);
//声明槽函数
public slots:
void acceptSignals(int sgl);
};
#endif // STUDENT_H
teacher.h
#ifndef TEACHER_H
#define TEACHER_H
#include <QObject>
class Teacher : public QObject
{
Q_OBJECT
public:
explicit Teacher(QObject *parent = nullptr);
//声明型号函数
signals:
void sendSingals(int sgl);
};
#endif // TEACHER_H
student.cpp
#include "student.h"
#include "QDebug"
Student::Student(QObject *parent)
: QObject{parent}
{}
void Student::acceptSignals(int sgl){
qDebug()<< "学生接收信号: "<< sgl;
}
teacher.cpp
#include "teacher.h"
#include "QDebug"
Teacher::Teacher(QObject *parent)
: QObject{parent}
{}
//信号函数只需要声明,不需要实现
mywidget.cpp
#include "mywidget.h"
#include "ui_mywidget.h"
#include "teacher.h"
#include "student.h"
#include <QPushButton>
void MyWidget::sendTo(){
emit t1->sendSingals(5);
}
MyWidget::MyWidget(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MyWidget)
{
ui->setupUi(this);
//有参传递
this->t1 = new Teacher(this);
this->s1 = new Student(this);
QObject::connect(t1,&Teacher::sendSingals,s1,&Student::acceptSignals);
// sendTo中通过emit触发
this->sendTo();
//当信号函数发生重载时
/*
void (Teacher:: *tp)(int) = &Teacher::sendSingals;
void (Student:: *sp)(int) = &Student::acceptSignals;
QObject::connect(t1,tp,s1,sp);
*/
//QString转char*输出字符串输出不带""
/*
先转成QByteArray,再转成char *
.toUtf8() .data()
*/
//通过按钮信号函数连接学生的槽函数
QPushButton *btn1 = new QPushButton("触发学生的槽",this);
connect(btn1,&QPushButton::clicked,s1,&Student::acceptSignals);
//通过按钮信号函数触发老师的信号函数
QPushButton *btn2 = new QPushButton("触发老师的信号",this);
btn2->move(200,0);
connect(btn2,&QPushButton::clicked,t1,&Teacher::sendSingals);
//断开信号
// disconnect(obj1,&classname1::func1,obj2,&classname2::func2);
/*
* 总结:
* 1.信号可以连接信号
* 2.一个信号可以连接多个槽
* 3.多个信号可以连接一个槽
* 4.信号函数和槽函数的参数必须类型按顺序一一对应
* 5.信号和槽的参数个数可以不对应,但信号的参数个数应该大于槽函数
* 6.QT4版本的写法 connect(obj1,SIGNAL(func(int)),obj2,SLOT(func(int)));
*/
}
MyWidget::~MyWidget()
{
delete ui;
}
五、底层原理
信号槽的底层依赖 Qt 元对象系统(moc)和事件循环,核心流程:
编译器预处理时,moc 扫描 Q_OBJECT 宏,生成 moc_xxx.cpp 文件(包含信号的实现、槽函数的注册);
信号发射(emit)时,本质是调用 moc 生成的信号函数,该函数遍历所有绑定的槽函数
1091

被折叠的 条评论
为什么被折叠?



