【QT学习】信号与槽(无线程交互)

一、简介

信号与槽(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 生成的信号函数,该函数遍历所有绑定的槽函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值