Qt-02:信号与槽

文章目录

信号与槽

什么是信号与槽函数

信号与槽(Signals and Slots)是一种用于对象间通信的机制,广泛应用于图形用户界面(GUI)编程,尤其在Qt框架中。其核心思想是通过松耦合的方式实现对象间的交互,无需显式调用对方的方法。

信号(Signal)是对象在特定事件发生时发出的通知。例如,按钮被点击时发出clicked信号,窗口关闭时发出closed信号。信号本身不包含具体的实现逻辑,仅作为事件触发的标志。

  • 信号由Qt的moc(元对象编译器)自动生成。
  • 信号可以携带参数,用于传递事件相关的数据。

槽(Slot)是普通的成员函数,用于响应信号。当信号被触发时,与之连接的槽函数会被自动调用。槽函数可以执行任何逻辑,例如更新界面、处理数据等。

  • 槽可以是任何类的成员函数,只需声明为public slots或使用Q_SLOTS宏。
  • 槽可以接受信号传递的参数,并与之匹配。

信号与槽的连接

通过QObject::connect函数建立信号与槽的关联。语法如下:

cpp 复制代码
QObject::connect(发送者, 信号, 接收者, 槽);

特性与优势

  1. 松耦合:发送者和接收者无需知道对方的具体实现,仅需通过信号与槽连接。
  2. 类型安全:Qt在编译时检查信号与槽的参数类型是否匹配。
  3. 多对多支持:一个信号可以连接多个槽,一个槽也可以响应多个信号。
  4. 跨线程通信 :通过Qt::QueuedConnection方式实现线程安全的异步调用。

注意事项

  • 信号与槽的参数数量和类型必须兼容,但允许槽的参数比信号少(忽略多余的参数)。
  • 使用disconnect可断开已建立的连接。
  • 在Qt5中推荐使用新式语法(函数指针),而非旧式的SIGNAL()SLOT()宏。

1. 字符串方式 SIGNAL / SLOT(Qt4)

cpp 复制代码
connect(sender, SIGNAL(signalName(parameters)), receiver, SLOT(slotName(parameters)));

2. 函数地址方式(Qt5)

cpp 复制代码
connect(sender, &SenderClass::signalName, receiver, &ReceiverClass::slotName);

3. Lambda表达式

可直接在connect中编写逻辑:

cpp 复制代码
connect(button, &QPushButton::clicked, this, []() {
  qDebug() << "Lambda slot called";
});

4. UI设计师界面-转到槽

5. UI设计师界面-信号槽编辑器

创建 ui 项目

勾选:Generate form

双击 widget.ui,进入编辑模式

进行信号与槽的连接

  • widget.cpp
cpp 复制代码
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 1. 使用 SIGNAL/SLOT 方式连接信号与槽
    connect(ui->pushButton_1, SIGNAL(clicked(bool)), this, SLOT(showMaximized()));

    // 2. 使用函数地址 方式连接信号与槽
    connect(ui->pushButton_2, &QPushButton::clicked, this, &Widget::showNormal);

    // 5. 使用 Lambda表达式做槽函数
    connect(ui->pushButton_5, &QPushButton::clicked, this, [&](){
        this->setWindowTitle("连接信号槽的5种方式");
    });
}

Widget::~Widget(){ delete ui; }

void Widget::on_pushButton_3_clicked(){
    // 3. 使用设计师界面-转到槽 方式连接信号与槽
    this->showMinimized();
}

连接重载的信号与槽

cpp 复制代码
#if 0
    // 1. 创建发送者、接收者对象
    Sender sender;
    Receiver receiver;

    // 2. 建立信号与槽的链接 Qt4
    QObject::connect(&sender, SIGNAL(click()), &receiver, SLOT(execute()));
    QObject::connect(&sender, SIGNAL(click(QString)), &receiver, SLOT(execute(QString)));

    // 3. 发送信号  emit 可省略
    emit sender.click();
    emit sender.click("overload");
    return a.exec(); // 让应用程序对象进入消息循环,应用程序就阻塞在这里
#endif

#if 1
    // 1. 创建发送者、接收者对象
    Sender sender;
    Receiver receiver;

    // 2. 建立信号与槽的链接 Qt5
    void (Sender::*pClick)() = &Sender::click;
    void (Receiver::*pExecute)() = &Receiver::execute;
    QObject::connect(&sender, pClick, &receiver, pExecute);

    void (Sender::*pClick2)(QString) = &Sender::click;
    void (Receiver::*pExecute2)(QString) = &Receiver::execute;
    QObject::connect(&sender, pClick2, &receiver, pExecute2);

    // 3. 发送信号 emit 可省略
    emit sender.click();
    emit sender.click("overload");
#endif

连接多个信号与槽函数

一个信号连接多个槽函数

多个信号连接一个槽函数

cpp 复制代码
#if 1
    // 一个信号连接多个槽函数
    Sender sender1,sender2;
    Receiver receiver1, receiver2;

    void (Sender::*click1)() = &Sender::click;
    void (Receiver::*execute1)() = &Receiver::execute;
    void (Receiver::*execute1_2)() = &Receiver::execute;

    QObject::connect(&sender1, click1, &receiver1, execute1);
    QObject::connect(&sender1, click1, &receiver1, execute1_2);

    emit sender1.click();

    // -------------------------------------------------------
    // 多个信号连接一个槽函数
    void (Sender::*click2)(QString) = &Sender::click;
    void (Sender::*click2_2)(QString) = &Sender::click;
    void (Receiver::*execute2)(QString) = &Receiver::execute;

    QObject::connect(&sender1, click2, &receiver2, execute2);
    QObject::connect(&sender2, click2_2, &receiver2, execute2);

    emit sender1.click("AAA");
    emit sender2.click("BBB");
#endif
相关推荐
知识分享小能手5 小时前
C++ 学习教程,从入门到精通,C++ 入门知识 — 完整知识点(1)
开发语言·c++·学习
+VX:Fegn08956 小时前
计算机毕业设计|基于springboot + vue旅游管理系统(源码+数据库+文档)
java·开发语言·vue.js·spring boot·课程设计
阿里嘎多学长6 小时前
2026-09-20 GitHub 热点项目精选
开发语言·程序员·github·代码托管
江湖人称菠萝包7 小时前
【Qt】《Qt 5.9 C++开发指南》笔记-Chapter9-Qt Charts
笔记·qt·qt5
扶尔魔ocy8 小时前
【QT android】环境安装及第一个QT项目
qt·andriod开发
weixin_307779138 小时前
C++代码实现MATLAB中的ode23tb函数功能
开发语言·c++·算法·matlab
2601_966949658 小时前
为什么量化回测中 for 循环比 DataFrame 慢三个数量级?从向量化原理讲起
开发语言·python·pandas·股票数据·quantdash
边境悍匪10 小时前
蜗牛学苑 Java 智能体学习 Day45|Knife4j+SpringBoot3、书城项目整合 MyBatis 思维导图复盘
java·开发语言·vue.js·学习·spring
我的xiaodoujiao10 小时前
Django 基础知识详细图文教程 9-Django 模板引擎 2
开发语言·数据库·后端·django
菜鸟~noob23310 小时前
【太空电子战】从CCS到Meadowlands:反通信系统的二十年演进史【含matlab代码】
开发语言·matlab