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
相关推荐
Eider19989 分钟前
python基础语法之并发基础练习
开发语言·python
#麻辣小龙虾#14 分钟前
网页布局css中flex+margin的组合布局技巧
开发语言·前端·javascript
云和数据.ChenGuang17 分钟前
python和java的try
java·开发语言·python
我是唐青枫18 分钟前
Kotlin Inheritance(继承)详解:语法、原理、实战 Demo
开发语言·kotlin
ly768928 分钟前
从 OpenAPI 到多语言 SDK 生成:Java 服务端契约漂移与生成器版本治理
java·开发语言·openapi·java 21·版本兼容·契约漂移·sdk 生成
lqbzlll42 分钟前
CVE-2026-91403 排查指南:Java JSSE 信任链漏洞的根因、影响范围和修复步骤
java·开发语言·信任链
CarIise1 小时前
AOP 概念的引入
java·开发语言
凉茶钱1 小时前
多态:从虚函数语法到虚表寻址,一次讲透动态绑定
开发语言·c++·多态
Hello.Reader1 小时前
Three.js / Cesium 卡顿怎么办?把三维渲染搬到 GPU 服务器
服务器·开发语言·javascript
Solange__1 小时前
AI世界模型、3D场景生成和游戏引擎怎么选?按5类任务比较交互、物理与导出
开发语言·人工智能·游戏·平面·3d·自然语言处理·游戏引擎