当前位置: 首页 > news >正文

Qt 入门简洁笔记:信号与槽

目录

  • Qt 信号与槽详解(从原理到应用)
    • 一、信号与槽机制概述
      • 1.1 示例场景
      • 1.2 信号与槽的本质
    • 二、信号与槽的使用
      • 2.1 `connect()` 函数的基本用法
      • 2.2 Qt Creator 自动生成信号与槽
    • 三、自定义信号与槽
      • 3.1 自定义信号规范
      • 3.2 自定义槽规范
      • 3.3 发射信号(emit)
    • 四、信号与槽的连接形式
    • 五、带参数的信号与槽
    • 六、断开信号与槽连接
    • 七、Qt4 与 Qt5 的区别
    • 八、使用 Lambda 表达式实现槽函数
      • 捕获方式总结
    • 九、信号与槽机制的优缺点分析
    • 十、总结
      • 免责声明


Qt 信号与槽详解(从原理到应用)

一、信号与槽机制概述

在 Qt 框架中,信号与槽(Signal & Slot) 是实现对象间通信的核心机制,用于事件驱动式编程。

当用户对界面控件进行操作时(如点击按钮、输入文字、关闭窗口),Qt 会将这些操作视为“事件”。
事件产生后,会触发相应的信号(Signal),而接收并响应这些信号的函数则称为槽(Slot)

简单来说:

信号 = “发生了某个事件”
= “如何响应这个事件”

1.1 示例场景

假设我们有一个按钮和一个窗口:

  • 按钮点击时会发出 clicked() 信号;
  • 窗口接收到信号后调用自身的 close() 槽函数,实现关闭操作。

两者通过 connect() 函数连接后,就可以实现 “点击按钮关闭窗口” 的功能。

1.2 信号与槽的本质

元素本质
信号(Signal)一种函数声明,表示事件发生
槽(Slot)一种普通函数,用于响应信号
连接机制Qt 在底层通过函数调用、参数封装等方式实现信号触发时的槽执行
元对象系统Qt 使用 MOC(Meta-Object Compiler)在编译前生成元数据,自动维护信号槽映射关系

二、信号与槽的使用

2.1 connect() 函数的基本用法

所有继承自 QObject 的类都可以使用 connect() 函数建立信号与槽的连接:

connect(const QObject *sender, const char *signal,const QObject *receiver, const char *method,Qt::ConnectionType type = Qt::AutoConnection);

参数说明:

  • sender:信号发送者对象;
  • signal:发送的信号(如 SIGNAL(clicked()));
  • receiver:信号接收者对象;
  • method:接收信号的槽函数(如 SLOT(close()));
  • type:连接类型,默认自动选择。

示例:

connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(close()));

此语句表示:当按钮点击时,调用窗口对象的 close() 槽。

2.2 Qt Creator 自动生成信号与槽

在 Qt Creator 中,我们可以直接在 UI 设计器中右键控件 → “转到槽…”,自动生成槽函数:

  • 槽函数命名规则:on_对象名_信号名()
    例如:on_pushButton_clicked()

自动生成的函数会在头文件中声明、源文件中定义。
不过在实际开发中,推荐显式使用 connect() 来建立连接,能提高可读性与维护性。


三、自定义信号与槽

除了使用系统内置信号外,开发者也可以定义自己的信号与槽,用于类之间的通信。

3.1 自定义信号规范

signals:void mySignal();void sendData(QString data);

注意事项:

  1. 必须写在 signals: 下;
  2. 返回值为 void
  3. 只需声明,不用实现;
  4. 可带参数,可重载。

3.2 自定义槽规范

public slots:void mySlot();void receiveData(QString data);

特点:

  • 槽函数与普通成员函数几乎相同;
  • 可以放在 public/private/protected slots: 下;
  • 需要声明与定义;
  • 可被手动调用。

3.3 发射信号(emit)

信号通过 emit 关键字发出:

emit mySignal();
emit sendData("Hello Qt");

emit 只是一个提示性的宏,不会影响逻辑。


四、信号与槽的连接形式

Qt 的信号与槽机制非常灵活,支持多种连接关系:

类型描述
一对一一个信号连接一个槽
一对多一个信号连接多个槽
多对一多个信号连接一个槽
信号连接信号信号触发后继续发出另一个信号

示例:一对多

connect(this, SIGNAL(updateUI()), this, SLOT(showText()));
connect(this, SIGNAL(updateUI()), this, SLOT(updateStatus()));

示例:信号连接信号

connect(this, SIGNAL(clicked()), this, SIGNAL(closeRequested()));

五、带参数的信号与槽

信号与槽的参数类型和个数需要匹配。
Qt 支持信号参数多于槽参数,但反之不行。

示例:

signals:void sendNumber(int num);public slots:void printNumber(int num);
connect(this, &MyWidget::sendNumber, this, &MyWidget::printNumber);
emit sendNumber(10);

信号参数会自动传递给槽函数的形参,实现数据传递。


六、断开信号与槽连接

使用 disconnect() 可解除连接:

disconnect(sender, SIGNAL(clicked()), receiver, SLOT(close()));

该函数与 connect() 参数形式一致。
在需要动态控制响应关系时非常有用。


七、Qt4 与 Qt5 的区别

Qt4 的信号槽机制使用字符串宏 SIGNAL()SLOT(),语法较旧:

connect(button, SIGNAL(clicked()), this, SLOT(close()));

Qt5 之后推荐使用函数指针语法,类型安全:

connect(button, &QPushButton::clicked, this, &QWidget::close);

优缺点比较:

版本优点缺点
Qt4参数直观无类型检查,易出错
Qt5类型安全、可用 Lambda写法稍长但更规范

八、使用 Lambda 表达式实现槽函数

C++11 引入了 Lambda 表达式,使槽函数可以内联定义,无需额外声明:

connect(ui->pushButton, &QPushButton::clicked, [=](){this->close();
});

捕获方式总结

捕获形式含义
[=]值捕获所有局部变量
[&]引用捕获所有局部变量
[this]捕获当前对象成员
[a, &b]单独指定捕获方式

示例:使用 Lambda 捕获外部变量

int count = 0;
connect(ui->pushButton, &QPushButton::clicked, [=]() mutable {count++;qDebug() << "Clicked times:" << count;
});

九、信号与槽机制的优缺点分析

优点缺点
实现模块之间的松散耦合性能略低于直接函数调用
可扩展、可维护性强需要 MOC 支持,构建复杂
类型安全(Qt5起)多线程信号可能需排队调度

实际上,信号槽机制的性能消耗在 GUI 应用中几乎可以忽略。
例如,普通函数调用可能耗时 10μs,而信号槽约 100μs,对用户而言无感。


十、总结

Qt 的信号与槽机制是 Qt 编程思想的核心,它不仅替代了传统的回调函数,更通过元对象系统提供了高度灵活、安全的事件通信机制。
掌握这一机制后,你可以:

  • 轻松编写组件化 UI;
  • 在对象间传递消息;
  • 使用 Lambda 优雅地响应用户操作。

建议学习路线:

  1. 理解 connect() 基本用法;
  2. 熟练掌握自定义信号与槽;
  3. 熟悉 Lambda 式写法;
  4. 理解 QObject 与元对象系统。

免责声明

本文部分内容参考自教学课件与官方 Qt 文档,版权归原作者所有。
本文仅用于学习与技术交流,不可用于商业用途。如有侵权,请联系删除。
本文不会设置为仅vip查看,如果发生该情况,皆为平台所为。

封面图来源于网络,如有侵权,请联系删除!

http://www.dtcms.com/a/523861.html

相关文章:

  • 算法入门---专题二:滑动窗口2(最大连续1的个数,无重复字符的最长子串 )
  • 手机摄像头如何识别体检的色盲检查图的数字和图案(下)
  • 政务系统信创改造中,金仓日志如何满足等保2.0三级审计要求
  • 记录一个监控网卡某个IP发送流量
  • Python-UnitTest框架
  • 模型-模型压缩:量化、剪枝、蒸馏、二值化
  • UE5 蓝图-12:pawn蓝图,轴映射-鼠标右键,补充轴映射与操作映射的区别。相机的旋转俯仰逻辑,伸缩逻辑,浮点差值函数 FInterpTo;
  • Vcenter7使用主机配置文件重置ESXI主机 root 密码
  • STL 容器:List
  • 做网站销售好累网上开店的货源渠道有哪些
  • 图像,视频Lora模型训练的Timestep Type时间步类型
  • 告别云端依赖!ComfyUI本地化视频生成实战教程+cpolar实战
  • Android16之如何获取APP、Bin进程的UID(二百六十三)
  • 在JavaScript / HTML中,无法通过开发者工具查看DOM元素中input里输入的密码
  • 像素塔防游戏:像素守卫者
  • 什么是栈?深入理解 JVM 中的栈结构
  • Go Web 编程快速入门 07.2 - 模板(2):解析与执行(含Demo)
  • 公司用wordpress建站用花钱大连网站设计开发
  • 建设网站需要下载神呢软件吗重庆企业网站推广公司
  • 常规面光源在工业视觉检测上的应用
  • 数据结构——直接插入排序
  • 如何开公司做网站素材免费网站
  • Spring Boot 配置优先级
  • 【架构】-- Nightingale:云原生监控告警平台的深度解析
  • 【Leetcode】
  • 以LIS为突破口的全栈信创实践——浙江省人民医院多院区多活架构建设样本
  • 使用 IntelliJ IDEA 连接 Docker
  • Maya Python入门: polySphere()球体的形状节点操作
  • 目前最好的引流方法上海专业seo
  • 第一篇使用HTML写一个随机点名网页