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

QT之巧用对象充当信号接收者

备注:以下仅为演示不代表合理性,适合简单任务,逻辑简单、临时使用,可保持代码简洁,对于复杂的任务应创建一个专门的类来管理信号和线程池任务.

FileScanner类继承QObject和QRunnable,扫描指定目录下的文件获取文件列表,逐个发出fileFound信号;

FileHasher:继承QObject和QRunnable,计算文件的SHA1值,发出hashResult信号;

1、使用新建临时对象 

#include <QCoreApplication>
#include <QThreadPool>
#include "global_threadpool_example.h"int main(int argc, char *argv[]) {QCoreApplication app(argc, argv);// 创建协调对象,处理信号QObject coordinator;// 启动文件扫描任务FileScanner *scanner = new FileScanner("/path/to/your/directory"); // 替换为实际目录QObject::connect(scanner, &FileScanner::fileFound, &coordinator, [&coordinator](const QString &filePath) {// 为每个找到的文件启动SHA1计算任务FileHasher *hasher = new FileHasher(filePath);QObject::connect(hasher, &FileHasher::hashResult, &coordinator, [](const QString &filePath, const QString &hash) {qDebug() << "File:" << filePath << "SHA1:" << hash;});QThreadPool::globalInstance()->start(hasher);});QObject::connect(scanner, &FileScanner::finished, &coordinator, []() {qDebug() << "Scanning finished.";// 可选:等待所有任务完成QThreadPool::globalInstance()->waitForDone();qDebug() << "All tasks completed.";});// 提交扫描任务到全局线程池QThreadPool::globalInstance()->start(scanner);return app.exec();
}
  • Qt 的信号槽机制要求信号的接收者是一个 QObject 或其派生类的实例。coordinator 是一个 QObject 实例,用于连接 FileScanner 和 FileHasher 发出的信号(如 fileFound 和 hashResult)。
  • 它充当信号的“中转站”,将任务的异步结果(例如找到的文件路径或计算的 SHA1 值)传递到处理逻辑中。
  • 它可以避免在 main 函数中创建额外的类或全局对象,保持代码简洁。

  • coordinator 是 main 函数的局部变量,其生命周期持续到程序退出。这足以处理所有信号,因为线程池任务的信号在事件循环中处理。

2、使用QCoreApplication对象

#include <QCoreApplication>
#include <QThreadPool>
#include "global_threadpool_example.h"int main(int argc, char *argv[]) {QCoreApplication app(argc, argv);// 启动文件扫描任务FileScanner *scanner = new FileScanner("/path/to/your/directory"); // 替换为实际目录QObject::connect(scanner, &FileScanner::fileFound, &app, [&app](const QString &filePath) {FileHasher *hasher = new FileHasher(filePath);QObject::connect(hasher, &FileHasher::hashResult, &app, [](const QString &filePath, const QString &hash) {qDebug() << "File:" << filePath << "SHA1:" << hash;});QThreadPool::globalInstance()->start(hasher);});QObject::connect(scanner, &FileScanner::finished, &app, []() {qDebug() << "Scanning finished.";QThreadPool::globalInstance()->waitForDone();qDebug() << "All tasks completed.";});// 提交扫描任务到全局线程池QThreadPool::globalInstance()->start(scanner);return app.exec();
}

QCoreApplication 是 Qt 应用程序的主对象,无需额外创建 QObject,app存在于整个程序生命周期,也可以直接用作信号槽连接的接收者,也适合信号槽逻辑简单、临时使用的场景。

缺点:语义上不够清晰,因为 QCoreApplication 的主要职责是管理应用程序,而不是任务协调,如果程序中有多个模块使用 app 处理信号,可能会导致信号槽逻辑混杂,这种方式并不推荐。

3、使用 lambda 表达式

#include <QCoreApplication>
#include <QThreadPool>
#include "global_threadpool_example.h"int main(int argc, char *argv[]) {QCoreApplication app(argc, argv);// 启动文件扫描任务FileScanner *scanner = new FileScanner("/path/to/your/directory"); // 替换为实际目录QObject::connect(scanner, &FileScanner::fileFound, [=](const QString &filePath) {FileHasher *hasher = new FileHasher(filePath);QObject::connect(hasher, &FileHasher::hashResult, [](const QString &filePath, const QString &hash) {qDebug() << "File:" << filePath << "SHA1:" << hash;});QThreadPool::globalInstance()->start(hasher);});QObject::connect(scanner, &FileScanner::finished, []() {qDebug() << "Scanning finished.";QThreadPool::globalInstance()->waitForDone();qDebug() << "All tasks completed.";});// 提交扫描任务到全局线程池QThreadPool::globalInstance()->start(scanner);return app.exec();
}

Qt 允许在信号连接中使用 lambda 表达式直接处理逻辑,无需显式的接收者对象。这种方式将信号处理逻辑直接嵌入 lambda 函数中。适合信号槽逻辑简单、临时使用的场景。

  • 代码更简洁,无需创建额外的 QObject,逻辑集中在 lambda 函数中,易于理解。
  • lambda 表达式无法像 QObject 那样方便地管理多个信号槽连接(例如断开连接),而且如果 lambda 中捕获了变量(如 [=]),特别需要注意捕获变量的生命周期。

4、使用静态函数或全局函数处理信号

#include <QCoreApplication>
#include <QThreadPool>
#include "global_threadpool_example.h"// 静态函数处理信号
static void handleFileFound(const QString &filePath) {FileHasher *hasher = new FileHasher(filePath);QObject::connect(hasher, &FileHasher::hashResult, [](const QString &filePath, const QString &hash) {qDebug() << "File:" << filePath << "SHA1:" << hash;});QThreadPool::globalInstance()->start(hasher);
}static void handleFinished() {qDebug() << "Scanning finished.";QThreadPool::globalInstance()->waitForDone();qDebug() << "All tasks completed.";
}int main(int argc, char *argv[]) {QCoreApplication app(argc, argv);// 启动文件扫描任务FileScanner *scanner = new FileScanner("/path/to/your/directory"); // 替换为实际目录QObject::connect(scanner, &FileScanner::fileFound, handleFileFound);QObject::connect(scanner, &FileScanner::finished, handleFinished);// 提交扫描任务到全局线程池QThreadPool::globalInstance()->start(scanner);return app.exec();
}

 定义静态函数 handleFileFound 和 handleFinished,直接连接到信号,不需要 QObject 接收者。但这种方式,静态函数无法方便地存储状态(如任务列表、结果收集),不易扩展,维护性较差,仅适合信号处理逻辑非常简单的情况。

http://www.xdnf.cn/news/8403.html

相关文章:

  • Linux进程 线程 进程间通信 IPC——管道
  • 全国青少年信息素养大赛-python编程—省赛真题—卡牌游戏
  • Redis配置文件详解
  • 树 Part 10
  • JFace中MVC的表的单元格编辑功能的实现
  • Datawhale_PyPOTS_task6
  • 【安全攻防与漏洞​】​​HTTPS中的常见攻击与防御​​
  • 机器人强化学习入门学习笔记(三)
  • 洛谷 P1800 software(DP+二分)【提高+/省选−】
  • 三步快速部署一个本地Windows/Linux大语言模型ChatGLM(环境配置+权重下载+运行)
  • AI架构分层原则
  • Stack主题遇到的问题
  • C# WinForm应用程序多语言实现全面指南
  • deepseek组合使用
  • 测试关键点
  • 【Kafka】编写消费者开发模式时遇到‘未解析的引用‘SIGUSR1’’
  • 掌握递归:编程中的优雅艺术
  • 精益数据分析(79/126):从黏性到爆发——病毒性增长的三种形态与核心指标解析
  • Swagger、Springfox、Springdoc-openapi 到底是什么关系
  • 使用 GPUStack 纳管摩尔线程 GPU 进行大语言模型和文生图模型的推理
  • ASPICE认证 vs. 其他标准:汽车软件开发的最优选择
  • C# UDP协议:核心原理、高效实现与实战进阶指南​
  • 2025语音语聊系统源码开发深度解析:WebRTC与AI降噪技术如何重塑语音社交体验
  • 智能存储如何应对极端环境挑战?忆联独家解锁PCIe 5.0固态存储“抗辐射”黑科技,重新定义数据安全防护新高度
  • 机会成本与沉没成本:如何做出理性经济决策
  • grafana/loki-stack 设置日志保存时间及自动清理
  • HarmonyOS NEXT~鸿蒙AI开发全解析:HarmonyOS SDK中的智能能力与应用实践
  • PCB设计教程【入门篇】——电路分析基础-读懂原理图
  • lanqiaoOJ 4330:欧拉函数模板
  • OceanBase 共享存储:云原生数据库的存储