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

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.lryc.cn/news/2385902.html

相关文章:

  • 《红警2000》游戏信息
  • Vue3 + ThinkPHP8 + PHP8.x 生态与 Swoole 增强方案对比分析
  • (九)PMSM驱动控制学习---高阶滑膜观测器
  • 25年上半年五月之软考之设计模式
  • Mongo DB | 多种修改数据库名称的方式
  • QListWidget的函数,信号介绍
  • Python类属性与实例属性的覆盖机制:从Vector2d案例看灵活设计
  • QML与C++交互2
  • EtherNet/IP机柜内解决方案在医疗控制中心智能化的应用潜能和方向分析
  • springboot中各模块间实现bean之间互相调用(service以及自定义的bean)
  • RabbitMQ 可靠性保障:消息确认与持久化机制(二)
  • QML学习07Property
  • Skywalking安装部署使用教程
  • 网络编程与axios技术
  • 【结构设计】以3D打印举例——持续更新
  • MySQL中的重要常见知识点(入门到入土!)
  • 理解全景图像拼接
  • 云原生安全基石:Linux进程隔离技术详解
  • 基于PySide6与pycatia的CATIA几何阵列生成器开发实践
  • Linux学习心得问题总结(三)
  • 蓝桥杯国14 不完整的算式
  • Anthropic推出Claude Code SDK,强化AI助理与自动化开发整合
  • 6.4.1最小生成树
  • DAY 33
  • 基于ICEEMDAN-SSA-BP的混合预测模型的完整实现过程
  • 常见排序算法详解及其复杂度分析
  • DARLR用于具有动态奖励的推荐系统的双智能体离线强化学习(论文大白话)
  • 第35节:PyTorch与TensorFlow框架对比分析
  • 企业级智能体 —— 企业 AI 发展的下一个风口?
  • 【软考向】Chapter 2 程序设计语言基础知识