Qt信号与槽机制及动态调用

Qt信号与槽机制及动态调用

  • 一、信号与槽
    • 1、Qt信号与槽机制概述
    • 2、信号与槽的基本使用
    • 3、信号与槽的特性
    • 4、使用Lambda表达式作为槽
    • 5、信号与槽的参数传递
    • 6、注意事项
  • 二、动态调用机制
    • 1、基本用法
    • 2、示例代码
    • 3、带参数的调用
    • 4、返回值处理
    • 5、信号与槽的动态连接
    • 6、动态方法调用
    • 7、应用场景

一、信号与槽

1、Qt信号与槽机制概述

      Qt的信号与槽机制是一种用于对象间通信的松散耦合设计模式。信号在特定事件发生时被触发,槽是响应信号的函数,两者通过QObject::connect建立关联。
      Qt的信号与槽机制是其核心特性之一,提供了一种对象间通信的强大方式。这种机制相比传统的回调函数有以下优势:

  • 类型安全:编译时检查类型
  • 松耦合:发射者不需要知道接收者的信息
  • 支持多对多通信:一个信号可以连接到多个槽,多个信号可以连接到一个槽
    在这里插入图片描述

2、信号与槽的基本使用

信号与槽的声明需在类中放置Q_OBJECT宏,并使用signalsslots关键字标记:

class MyClass : public QObject {Q_OBJECT
public slots:void respondToSignal();  // 槽函数
signals:void mySignal();         // 信号
};

连接信号与槽:

QObject::connect(sender, &SenderClass::signalName, receiver, &ReceiverClass::slotName);

3、信号与槽的特性

  • 自动断开:当对象被销毁时,连接自动断开。
  • 多对多连接:一个信号可连接多个槽,一个槽可响应多个信号。
  • 线程安全:跨线程通信通过Qt::QueuedConnection实现。

4、使用Lambda表达式作为槽

Qt5允许Lambda表达式直接作为槽函数:

QObject::connect(button, &QPushButton::clicked, [=]() {qDebug() << "Button clicked";
});

5、信号与槽的参数传递

信号和槽的参数需兼容(类型和数量匹配或槽的参数更少):

// 信号声明
signals:void dataSent(const QString &message);// 槽声明
public slots:void handleData(const QString &msg);// 连接
connect(this, &MyClass::dataSent, receiver, &ReceiverClass::handleData);

6、注意事项

  • 性能:信号与槽比直接函数调用稍慢,但灵活性更高。
  • 循环连接:避免信号与槽互相触发导致无限循环。
  • 默认参数:槽函数可忽略信号的尾部参数。

通过合理使用信号与槽,可以构建高度模块化且易于维护的Qt应用程序。

二、动态调用机制

除了直接连接信号和槽外,Qt还提供了动态调用的机制,主要通过QMetaObject::invokeMethod()实现。这种方式允许通过字符串名称来调用方法,提供了更大的灵活性。

QMetaObject::invokeMethod()

这个静态方法允许你通过方法名称字符串来调用对象的成员函数。它可以调用:

  • 槽函数
  • 标记为Q_INVOKABLE的常规成员函数

1、基本用法

bool QMetaObject::invokeMethod(QObject *obj, const char *member,Qt::ConnectionType type = Qt::AutoConnection,QGenericReturnArgument ret = QGenericArgument(0),QGenericArgument val0 = QGenericArgument(0),QGenericArgument val1 = QGenericArgument(),QGenericArgument val2 = QGenericArgument(),QGenericArgument val3 = QGenericArgument(),QGenericArgument val4 = QGenericArgument(),QGenericArgument val5 = QGenericArgument(),QGenericArgument val6 = QGenericArgument(),QGenericArgument val7 = QGenericArgument(),QGenericArgument val8 = QGenericArgument(),QGenericArgument val9 = QGenericArgument());}

2、示例代码

// 示例1:简单的invokeMethod调用
void AutoSaver::saveIfNecessary() {if(!QMetaObject::invokeMethod(parent(), "save")) {qWarning() << "AutoSaver: error invoking save() on parent";}
}

3、带参数的调用

// 示例2:带参数的invokeMethod调用
QByteArray buffer;
const bool b = QMetaObject::invokeMethod(m_thread, "calculateSpectrum",Qt::AutoConnection,Q_ARG(QByteArray, buffer),Q_ARG(int, format.frequency()),Q_ARG(int, bytesPerSample));

这里使用了Q_ARG宏来传递参数,它创建了一个QGenericArgument对象,封装了参数的类型和值信息。

4、返回值处理

如果需要获取被调用方法的返回值,可以使用Q_RETURN_ARG宏:

// 示例3:获取返回值的invokeMethod调用
QString result;
if (QMetaObject::invokeMethod(obj, "computeSomething",Qt::DirectConnection,Q_RETURN_ARG(QString, result),Q_ARG(int, 42))) {qDebug() << "Result:" << result;
} else {qWarning() << "Invocation failed";
}

5、信号与槽的动态连接

通过字符串名称动态连接:

QObject::connect(sender, SIGNAL(signalName()), receiver, SLOT(slotName()));

使用QMetaObject动态连接:

int signalIndex = sender->metaObject()->indexOfSignal("signalName()");
int slotIndex = receiver->metaObject()->indexOfSlot("slotName()");
QMetaObject::connect(sender, signalIndex, receiver, slotIndex);

6、动态方法调用

使用QMetaObject::invokeMethod:

// 同步调用
QMetaObject::invokeMethod(obj, "methodName", Qt::DirectConnection, Q_RETURN_ARG(QString, result),Q_ARG(int, param1),Q_ARG(QString, param2));// 异步调用
QMetaObject::invokeMethod(obj, "methodName", Qt::QueuedConnection,Q_ARG(int, param1));

7、应用场景

动态调用常见应用场景:

  • 插件系统:动态加载和调用插件功能
  • 脚本集成:从脚本语言调用Qt对象方法
  • 反射系统:实现通用对象操作接口
  • 动态UI:根据配置文件生成界面并绑定行为

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/90392.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/90392.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

K8s系列之:Kubernetes 的 OLM

K8s系列之:Kubernetes 的 OLM 什么是 Kubernetes 的 OLM什么是Kubernetes中的OperatorOLM 的功能OLM 的核心组件OLM优势OLM 的工作原理OLM 与 OperatorHub 的关系OLM示例场景什么是CRDoperator 和 CRD的关系为什么需要 CRD 和 OperatorCRD定义资源类型DebeziumServer如何使用d…

前端-HTML-day2

目录 1、无序列表 2、有序列表 3、定义列表 4、表格-基本使用 5、表格-结构标签 6、表格-合并单元格 7、表单-input基本使用 8、表单-input占位文本 9、表单-单选框 10、表单-上传多个文件 11、表单-多选框 12、表单-下拉菜单 13、表单-文本域 14、表单-label标签…

两种方式清除已经保存的git账号密码

方式一随便选择一个文件夹&#xff0c;然后鼠标右键-》TortoiseGit ->设置选择已保存的数据-》认证数据-》清除-》点击确定方式二 控制面板\用户帐户\凭据管理器-》windows凭据普通凭据-》找到git信息-》选择删除

Using Spring for Apache Pulsar:Message Production

1. Pulsar Template在Pulsar生产者端&#xff0c;Spring Boot自动配置提供了一个用于发布记录的PulsarTemplate。该模板实现了一个名为PulsarOperations的接口&#xff0c;并提供了通过其合约发布记录的方法。这些send API方法有两类&#xff1a;send和sendAsync。send方法通过…

CSS揭秘:10.平行四边形

前置知识&#xff1a;基本的css变形一、平行四边形 要实现一个平行四边形&#xff0c;可以使用CSS的skew变形属性来倾斜元素。 transform: skewX(-45deg);图-1显示容器和内容都出现了倾斜&#xff0c;该如何解决这个问题&#xff1f; 二、嵌套方案 我们通过将内容嵌套 div 并使…

深度学习 必然用到的 线性代数知识

把标量到张量、点积到范数全串起来&#xff0c;帮你从 0 → 1 搭建 AI 数学底座 &#x1f680; 1 标量&#xff1a;深度学习的最小单元 标量 就是一维空间里的“点”&#xff0c;只有大小没有方向。例如温度 52 F、学习率 0.001。 记号&#xff1a;普通小写 x&#xff1b;域&am…

OpenGL ES 纹理以及纹理的映射

文章目录开启纹理创建纹理绑定纹理生成纹理纹理坐标图像配置线性插值重复效果限制拉伸完整代码在 Android OpenGL ES 中使用纹理&#xff08;Texture&#xff09;可以显著提升图形渲染的质量和效率。以下是使用纹理的主要好处&#xff1a; 增强视觉真实感 纹理可以将复杂的图像…

从金字塔到个性化路径:AI 正在重新定义学习方式

几十年来&#xff0c;我们的教育系统始终遵循着一条熟悉的路线&#xff1a; 从小学、初中、高中&#xff0c;再到大学和研究生。这条标准化的路径&#xff08;K-12 到研究所&#xff09;结构清晰&#xff0c;却也缓慢。但在当今这个信息爆炸、知识快速更新、个性化需求高涨的时…

产品经理岗位职责拆解

以下是产品经理岗位职责的详细分解表&#xff0c;涵盖工作内容、核心动作及输出成果&#xff1a;岗位职责具体工作内容输出成果1. 日常版本迭代管理需求分析及PRD产出协调资源推动产品上线- 收集业务/用户需求&#xff0c;分析可行性及优先级- 撰写PRD文档&#xff0c;明确功能…

后端微服务基础架构Spring Cloud

版本关系 版本发布说明-阿里云Spring Cloud Alibaba官网 选择 创建项目 创建父项目 什么都不动&#xff0c;创建即可 1) 删掉没用的文件 保留 2) pom中加入 打包方式 <packaging>pom</packaging> 3) 删掉src 4) pom.xml中删除没用的 5)更改pom.xml中 spring…

数据分析框架和方法

一、核心分析框架 (The Big Picture Frameworks)​​描述性分析 (What Happened?)​​​​目的&#xff1a;​​ 了解过去发生了什么&#xff0c;描述现状&#xff0c;监控业务健康。​​核心工作&#xff1a;​​ 汇总、聚合、计算基础指标 (KPI)&#xff0c;生成报表和仪表盘…

电路研究9.3.10——合宙Air780EP中的AT开发指南:阿里云应用指南

这个好像也用不到&#xff0c;不过可以先贴出来。简单看了一下也没深入分析&#xff0c;直接扒过来了&#xff0c;感觉涉及到了上位机的学习了。我这下位机的可能用不到&#xff0c;就是贴过来好了。 应用概述 使用 AT 方式连接阿里云分为一机一密和一型一密&#xff0c;其中一…

[Backlog] 核心协调器 | 终端用户界面(TUI)实现 | 多分支任务冲突解决 | 测试验证体系

第8章 核心协调器 欢迎回到Backlog.md&#xff01; 在上一章文件系统操作中&#xff0c;我们深入了解了数据物理存储层面的读写机制。本章将聚焦系统的神经中枢——核心协调器。 核心协调器的本质&#xff08;中央决策引擎&#xff09; 如果将Backlog.md视为项目管理团队&a…

车载以太网-TC8测试-UT(Upper Tester)

目录 一、技术原理:指令体系与协议适配1. **指令格式与传输机制**2. **协议栈交互逻辑**3. **规范遵循与版本演进**二、测试应用:TC8测试场景与案例1. **TCP协议栈深度验证**2. **ARP协议健壮性测试**3. **SOME/IP服务动态管理**三、实现挑战与解决方案1. **实时性要求**2. *…

扣子Coze纯前端部署多Agents

纯前端网页搭建&#xff0c;无需任何后端代码&#xff0c;方便快捷&#xff01; 就像公司前台的多功能控制台&#xff0c;员工可以通过按钮快速呼叫不同的AI助手。具备多设备适配、智能对话等基础能力。 支持添加多个智能体 配置方式 添加智能体信息&#xff0c;data-bot为智…

STM32中I2C协议详解

前言 在嵌入式系统中&#xff0c;设备间的短距离通信协议中&#xff0c;I2C&#xff08;Inter-Integrated Circuit&#xff0c;集成电路互连&#xff09;以其信号线少、布线简单、支持多从机等特点&#xff0c;被广泛应用于传感器、EEPROM、OLED屏等中低速外设的通信场景。与SP…

解锁Spring Boot多项目共享Redis:优雅Key命名结构指南

引言Redis 基础与 Spring Boot 集成Redis 简介Redis&#xff0c;即 Remote Dictionary Server&#xff0c;是一个开源的基于内存的数据结构存储系统&#xff0c;可用作数据库、缓存和消息中间件 。它具备诸多显著特性&#xff0c;使其在现代软件开发中占据重要地位。Redis 的读…

《重构项目》基于Apollo架构设计的项目重构方案(多种地图、多阶段、多任务、状态机管理)

1. 项目结构设计project/ ├── config/ # 配置文件&#xff08;定义 Scenario、Stage、Task 的映射&#xff09; ├── src/ │ ├── base/ # 抽象基类定义 │ │ ├── scenario_base.h/.cpp │ │ ├── stage_base.h/.cpp…

动手学深度学习13.6. 目标检测数据集-笔记练习(PyTorch)

以下内容为结合李沐老师的课程和教材补充的学习笔记&#xff0c;以及对课后练习的一些思考&#xff0c;自留回顾&#xff0c;也供同学之人交流参考。 本节课程地址&#xff1a;数据集_哔哩哔哩_bilibili 本节教材地址&#xff1a;13.6. 目标检测数据集 — 动手学深度学习 2.0…

Unity3D游戏内存优化指南

前言 Unity3D 游戏的内存控制是保证游戏流畅运行&#xff08;尤其在移动端和主机平台&#xff09;和避免崩溃的关键挑战。以下是核心策略和常见问题的解决方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&#xff0c;希望大家可以点击进来一起交流一下开发经验…