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 接收者。但这种方式,静态函数无法方便地存储状态(如任务列表、结果收集),不易扩展,维护性较差,仅适合信号处理逻辑非常简单的情况。
相关文章:
QT之巧用对象充当信号接收者
备注:以下仅为演示不代表合理性,适合简单任务,逻辑简单、临时使用,可保持代码简洁,对于复杂的任务应创建一个专门的类来管理信号和线程池任务. FileScanner类继承QObject和QRunnable,扫描指定目录下的文件获…...
《红警2000》游戏信息
游戏背景:与《红色警戒》系列的其他版本类似,基于红警 95 的背景设定,讲述了第二次世界大战期间,世界各国为了争夺全球霸权而展开战争。游戏画面与音效:在画面上相比早期的红警版本有一定提升,解析度更高&a…...
Vue3 + ThinkPHP8 + PHP8.x 生态与 Swoole 增强方案对比分析
一、基础方案:Vue3 ThinkPHP8 PHP8.x 传统架构 优点 成熟稳定 组合经过长期验证,文档和社区资源丰富ThinkPHP8 对PHP8.x有良好支持,性能比PHP7提升20-30% 开发效率高 TP8的ORM和路由系统大幅减少样板代码Vue3组合式API Vite开发…...

(九)PMSM驱动控制学习---高阶滑膜观测器
在之前的文章中,我们介绍了永磁同步电机无感控制中的滑模观测器,但是同时我们也认识到了他的缺点:因符号函数带来的高频切换分量,使用低通滤波器引发相位延迟;在本篇文章,我们将会介绍高阶滑模观测器的无感…...

25年上半年五月之软考之设计模式
目录 一、单例模式 二、工厂模式 三、 抽象工厂模式 四、适配器模式 五、策略模式 六、装饰器模式 编辑 考点:会挖空super(coffeOpertion); 七、代理模式 为什么必须要使用代理对象? 和装饰器模式的区别 八、备忘录模式 一、单例模式 这个…...

Mongo DB | 多种修改数据库名称的方式
目录 方法一:使用 mongodump 和 mongorestore 命令 方法二:使用 db.copyDatabase() 方法 方法三:使用 MongoDB Compass 在 MongoDB 中,更改数据库名称并不是一个直接的操作,因为 MongoDB 不提供直接重命名数据库的命…...

QListWidget的函数,信号介绍
前言 Qt版本:6.8.0 该类用于列表模型/视图 QListWidgetItem函数介绍 作用 QListWidget是Qt框架中用于管理可交互列表项的核心组件,主要作用包括: 列表项管理 支持动态添加/删除项:addItem(), takeItem()批量操作:addItems()…...
Python类属性与实例属性的覆盖机制:从Vector2d案例看灵活设计
类属性与实例属性的交互机制 Python中类属性与实例属性的关系体现了语言的动态特性。当访问一个实例属性时,Python会首先查找实例自身的__dict__,如果找不到,才会去查找类的__dict__。这种机制使得类属性可以优雅地作为实例属性的默认值。 …...
QML与C++交互2
在QML与C的交互中,主要有两种方式:在C中调用QML的方法和在QML中调用C的方法。以下是具体的实现方法。 在C中调用QML的方法 首先,我们需要在QML文件中定义一个函数,然后在C代码中调用它。 示例 //QML main.qml文件 import QtQu…...

EtherNet/IP机柜内解决方案在医疗控制中心智能化的应用潜能和方向分析
引言 在数智化转型浪潮席卷各行各业的今天,医疗领域同样面临着提升运营效率、改善患者体验和加强系统可靠性的多重挑战。Rockwell Automation于2025年5月20日推出的EtherNet/IP机柜内解决方案,为医疗中心的自动化升级提供了一种创新路径。本报告将深入分析这一解决方案的核心…...
springboot中各模块间实现bean之间互相调用(service以及自定义的bean)
springboot中各模块间实现bean之间互相调用(service以及自定义的bean) https://blog.csdn.net/qq_29477175/article/details/122827446?ops_request_misc&request_id&biz_id102&utm_termspringboot%E5%A4%9A%E6%A8%A1%E5%9D%97%E4%B9%8B%E…...
RabbitMQ 可靠性保障:消息确认与持久化机制(二)
四、持久化机制:数据安全的护盾 (一)交换机持久化 交换机持久化是确保消息路由稳定的重要保障 。在 RabbitMQ 中,交换机负责接收生产者发送的消息,并根据路由规则将消息路由到相应的队列 。如果交换机在 RabbitMQ 重…...
QML学习07Property
Property 1、Property1.1 定义控件1.2 给控件取别名,不向外暴露控件名字 2、总结 1、Property property int myTopMargin: 0 property int myBottomMargin: 0 property real myReal: 0.0 //双精度浮点数 property string myString: "test" property…...
Skywalking安装部署使用教程
目录 核心功能 架构设计 安装与配置 使用场景 社区与支持 总结 官网 https:///apache/skywalking 部署Skywalking 添加报警配置 自定义告警规则如果您需要自定义告警规则,则需要编辑 alarm-settings.yml 文件并添加自定义的规则。具体来说,您需要按照 YAML 格式定义…...
网络编程与axios技术
网络编程技术是指通过计算机网络实现不同设备之间数据交互的技术。它基于网络通信协议(如TCP/IP、HTTP)和编程语言的支持,结合库和API实现高效的数据传输与通信。以下是几种主流技术栈(JavaScript、TypeScript、React、Next.js、P…...

【结构设计】以3D打印举例——持续更新
【结构设计】以立创EDA举例——持续更新 文章目录 [TOC](文章目录) 前言立创EDA官网教程一、3D外壳绘制二、3D外壳渲染三、3D外壳打印1.3D打印机——FDM2.3D打印机——光固化 四、3D外壳LOG设计1.激光雕刻机 总结 前言 提示:以下是本篇文章正文内容,下面…...

MySQL中的重要常见知识点(入门到入土!)
基础篇 基础语法 添加数据 -- 完整语法 INSERT INTO 表名 (字段名1, 字段名2, ...) VALUES (值1, 值2, ...);-- 示例 insert into employee(id,workno,name,gender,age,idcard,entrydate) values(1,1,Itcast,男,10,123456789012345678,2000-01-01) 修改数据 -- 完整语法 UPDA…...

理解全景图像拼接
1 3D到2D透视投影 三维空间上点 p 投影到二维空间 q 有两种方式:1)正交投影,2)透视投影。 正交投影直接舍去 z 轴信息,该模型仅在远心镜头上是合理的,或者对于物体深度远小于其到摄像机距离时的近似模型。…...

云原生安全基石:Linux进程隔离技术详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 进程隔离是操作系统通过内核机制将不同进程的运行环境和资源访问范围隔离开的技术。其核心目标在于: 资源独占:确保…...

基于PySide6与pycatia的CATIA几何阵列生成器开发实践
引言:参数化设计的工业价值 在航空航天、汽车制造等领域,复杂几何图案的批量生成是模具设计与机械加工的核心需求。传统手动建模方式存在效率低下、参数调整困难等问题。本文基于PySide6+pycatia技术栈,实现了一套支持动态参数配置、智能几何阵列生成的自动…...

Linux学习心得问题总结(三)
day09 文件权限篇 文件权限的属性有哪些?我们应如何理解这些属性? 文件权限的属性包括可读(r)、可写(w)、可执行(x)三种权限,根据文件类型可分为普通文件(.…...
蓝桥杯国14 不完整的算式
!!!!!!!!!!!!!!!理清思路 然后一步步写 问题描述 小蓝在黑板上写了一个形如 AopBC 的算式&#x…...

Anthropic推出Claude Code SDK,强化AI助理与自动化开发整合
Anthropic发布Claude Code SDK,协助开发团队将人工智慧助理整合进自动化开发流程,支援多轮对话、MCP协定及多元格式。 Anthropic推出Claude Code SDK,提供开发者与企业一套可程序化整合Claude AI助理至开发流程的工具。此SDK以命令列介面为基…...

6.4.1最小生成树
知识总览 生成树(一定是连通的): 是连通的无向图的一个子图,子图包含这个无向图的所有顶点有n-1条边(少一条边,生成树就不连通了)即为生成树,一个连通图可能有多个生成树 最小生成树(最小代价树): 只有连通的无向图才…...
DAY 33
知识点回顾: 1. PyTorch和cuda的安装 2. 查看显卡信息的命令行命令(cmd中使用) 3. cuda的检查 4. 简单神经网络的流程 a. 数据预处理(归一化、转换成张量) b. 模型的定义 i. 继承nn.Module类 ii. 定义…...
基于ICEEMDAN-SSA-BP的混合预测模型的完整实现过程
以下将为您详细阐述基于ICEEMDAN-SSA-BP的混合预测模型的完整实现过程,包含原理说明、算法实现、代码解析及优化策略。本教程分为六个核心部分,采用Python 3.9环境开发。 基于ICEEMDAN-SSA-BP的混合时间序列预测模型 一、模型架构设计 1.1 整体流程 #mermaid-svg-o4UD3HaTm…...
常见排序算法详解及其复杂度分析
常见排序算法详解及其复杂度分析 排序算法是数据结构与算法学习中的基础内容,也是面试高频考点。本文将系统介绍几种常见的排序算法,包括它们的原理、时间复杂度、空间复杂度以及 Python 实现方法。 一、冒泡排序(Bubble Sort) …...

DARLR用于具有动态奖励的推荐系统的双智能体离线强化学习(论文大白话)
1. 概述 离线强化学习是现在强化学习研究的一个重点。相比与传统的强化学习它不需要大量的实时交互数据,仅仅依赖历史交互日志就可以进行学习。本文就是将离线强化学习用于推荐系统的一篇文章。 这篇文章主要解决的核心问题有以下几个: 1)…...

第35节:PyTorch与TensorFlow框架对比分析
引言 在深度学习领域,PyTorch和TensorFlow无疑是当前最受欢迎的两大开源框架。 自2015年TensorFlow由Google Brain团队发布,以及2016年Facebook的AI研究团队推出PyTorch以来,这两个框架一直在推动着深度学习研究和工业应用的发展。 本文将从多个维度对这两个框架进行详细对…...

企业级智能体 —— 企业 AI 发展的下一个风口?
在AI技术迅猛发展的当下,企业对AI的应用不断深入。企业级智能体逐渐受到关注,它会是企业AI发展的下一个风口吗?先来看企业典型的AI应用场景,再深入了解企业级智能体。 企业典型AI应用场景 1. 内容生成:2025年…...