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
相关推荐
、BeYourself2 小时前
Scala 数据类型
开发语言·后端·scala
重生之后端学习2 小时前
136. 只出现一次的数字
开发语言·算法·leetcode·职场和发展·深度优先
啊唯不困2 小时前
AI智能应用开发(Java)起点-终点 -1、java的前世今生andJava环境配置、jdk下载,以及Idea下载和基本应用
java·开发语言·intellij-idea
大迪deblog2 小时前
系统架构设计-软件架构风格
java·开发语言·架构·软件构建
csbysj20202 小时前
Bootstrap 弹出框
开发语言
重庆小透明2 小时前
【面试问题】java小厂
java·开发语言·面试
CodeCraft Studio3 小时前
Parasoft C/C++嵌入式软件测试解决方案:安全、可靠且符合标准
开发语言·c++·安全·单元测试·代码规范·parasoft·嵌入式软件测试
森G3 小时前
22、GUI控件类---------常见界面组件类
qt
咚为3 小时前
Rust 跨平台编译实战:从手动配置到 Cross 容器化
开发语言·后端·rust