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
相关推荐
OOJO1 小时前
c++---list介绍
c语言·开发语言·数据结构·c++·算法·list
笨笨饿3 小时前
29_Z变换在工程中的实际意义
c语言·开发语言·人工智能·单片机·mcu·算法·机器人
艾为电子3 小时前
【技术帖】让接口不再短命:艾为 C-Shielding™ Type-C智能水汽防护技术解析
c语言·开发语言
棉花骑士3 小时前
【AI Agent】面向 Java 工程师的Claude Code Harness 学习指南
java·开发语言
IGAn CTOU4 小时前
PHP使用Redis实战实录2:Redis扩展方法和PHP连接Redis的多种方案
开发语言·redis·php
环黄金线HHJX.4 小时前
TSE框架配置与部署详解
开发语言·python
Vfw3VsDKo4 小时前
Maui 实践:Go 接口以类型之名,给 runtime 传递方法参数
开发语言·后端·golang
Pyeako4 小时前
PyQt5 + PaddleOCR实战:打造桌面级实时文字识别工具
开发语言·人工智能·python·qt·paddleocr·pyqt5
白藏y5 小时前
【C++】muduo接口补充
开发语言·c++·muduo
zk_one6 小时前
【无标题】
开发语言·前端·javascript