QT中多线程的实现

采用官方推荐的 QObject::moveToThread 方式实现(相比继承 QThread 更灵活),包含耗时任务执行、主线程通信、线程安全退出等核心功能。

环境说明

  • Qt 版本:Qt 5.15+ 或 Qt 6(兼容)
  • 项目类型:GUI 程序(含界面显示线程状态和结果)
  • 依赖模块:需在 .pro 文件中添加 QT += core gui widgets

完整代码(含注释)

1. 项目文件(.pro)
QT       += core gui widgets
CONFIG   += c++11TARGET = QtMultiThreadDemo
TEMPLATE = appSOURCES += main.cpp \mainwindow.cppHEADERS += \mainwindow.h \worker.hFORMS += mainwindow.ui
2. 工作类(worker.h)
#ifndef WORKER_H
#define WORKER_H#include <QObject>
#include <QThread>
#include <QDebug>// 工作类:负责执行耗时任务(如数据计算、文件读写等)
class Worker : public QObject {Q_OBJECT
public:explicit Worker(QObject *parent = nullptr) : QObject(parent) {}signals:// 发送任务进度(参数:当前进度,总进度)void progressUpdated(int current, int total);// 发送任务结果(参数:结果字符串)void resultReady(const QString &result);public slots:// 启动任务的槽函数(将在子线程中执行)void startTask() {const int totalSteps = 10;for (int i = 0; i <= totalSteps; ++i) {// 模拟耗时操作(如计算、延迟)QThread::msleep(500); // 暂停 500ms// 发送进度(跨线程信号,自动排队到主线程)emit progressUpdated(i, totalSteps);}// 发送最终结果emit resultReady("任务完成!总耗时:5秒");}
};
3. 主窗口类(mainwindow.h)
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QThread>
#include "worker.h"QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow {Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:// 点击按钮启动任务void on_startBtn_clicked();// 接收进度更新的槽函数(主线程执行)void onProgressUpdated(int current, int total);// 接收任务结果的槽函数(主线程执行)void onResultReady(const QString &result);private:Ui::MainWindow *ui;QThread *workerThread; // 子线程对象Worker *worker;        // 工作类实例
};
#endif
4. 主窗口实现(mainwindow.cpp)
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this);setWindowTitle("Qt 多线程示例");// 初始化子线程和工作类workerThread = new QThread(this); // 父对象设为窗口,自动管理生命周期worker = new Worker();            // 工作类无父对象(后续移动到子线程)// 将工作类移动到子线程worker->moveToThread(workerThread);// 连接信号槽(跨线程自动队列)connect(ui->startBtn, &QPushButton::clicked, this, &MainWindow::on_startBtn_clicked);connect(worker, &Worker::progressUpdated, this, &MainWindow::onProgressUpdated);connect(worker, &Worker::resultReady, this, &MainWindow::onResultReady);// 子线程结束时释放工作类(可选)connect(workerThread, &QThread::finished, worker, &QObject::deleteLater);
}MainWindow::~MainWindow() {// 窗口关闭时,停止子线程并等待退出workerThread->quit();workerThread->wait(); // 等待线程结束(避免强制终止导致资源泄漏)delete ui;
}// 点击按钮启动任务
void MainWindow::on_startBtn_clicked() {if (!workerThread->isRunning()) {// 启动子线程(不直接执行任务,而是触发工作类的槽函数)workerThread->start();// 调用工作类的 startTask 槽函数(在子线程中执行)QMetaObject::invokeMethod(worker, "startTask", Qt::QueuedConnection);ui->startBtn->setEnabled(false); // 防止重复点击}
}// 更新进度(主线程执行)
void MainWindow::onProgressUpdated(int current, int total) {ui->progressBar->setRange(0, total);ui->progressBar->setValue(current);ui->statusLabel->setText(QString("进度:%1/%2").arg(current).arg(total));
}// 接收任务结果(主线程执行)
void MainWindow::onResultReady(const QString &result) {ui->statusLabel->setText(result);ui->startBtn->setEnabled(true); // 允许再次启动workerThread->quit(); // 任务完成后停止子线程(可选)
}
5. 主函数(main.cpp)
#include "mainwindow.h"
#include <QApplication>int main(int argc, char *argv[]) {QApplication a(argc, argv);MainWindow w;w.show();return a.exec();
}
6. 界面文件(mainwindow.ui)

通过 Qt Designer 设计界面,包含以下控件(可直接复制 XML 到 .ui 文件):

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"><class>MainWindow</class><widget class="QMainWindow" name="MainWindow"><property name="geometry"><rect><x>0</x><y>0</y><width>400</width><height>200</height></rect></property><property name="windowTitle"><string>Qt 多线程示例</string></property><widget class="QWidget" name="centralwidget"><layout class="QVBoxLayout" name="verticalLayout"><item><widget class="QProgressBar" name="progressBar"><property name="value"><number>0</number></property></widget></item><item><widget class="QLabel" name="statusLabel"><property name="text"><string>点击按钮启动任务</string></property></widget></item><item><widget class="QPushButton" name="startBtn"><property name="text"><string>启动任务</string></property></widget></item></layout></widget></widget>
</ui>

代码核心逻辑说明

1. 多线程实现方式

采用 QObject::moveToThread 方式,将工作类 Worker 移动到子线程中执行任务,而非直接继承 QThread 并重写 run()。这种方式的优势:

  • 工作类通过信号槽与主线程通信,符合 Qt 事件驱动模型。
  • 支持多个任务在同一个线程中顺序执行(通过队列槽函数调用)。
2. 线程通信
  • 子线程→主线程:通过信号 progressUpdatedresultReady 发送进度和结果,Qt 会自动将信号排队到主线程执行(跨线程信号槽默认使用 Qt::QueuedConnection)。
  • 主线程→子线程:通过 QMetaObject::invokeMethod 调用子线程中的槽函数(startTask),确保在子线程上下文中执行。
3. 线程安全退出
  • 窗口关闭时,调用 workerThread->quit() 通知子线程退出事件循环,workerThread->wait() 等待线程完全停止,避免资源泄漏。
  • 子线程结束时,通过 connect(workerThread, &QThread::finished, worker, &QObject::deleteLater) 自动释放工作类实例。
4. 界面交互
  • 点击“启动任务”按钮后,按钮禁用(setEnabled(false)),防止重复触发。
  • 进度条(QProgressBar)实时显示任务进度,状态标签显示文字提示。

运行效果

  1. 编译运行程序,点击“启动任务”按钮。
  2. 进度条每秒更新一次(总耗时 5 秒),状态标签显示当前进度(如“进度:3/10”)。
  3. 任务完成后,状态标签显示“任务完成!总耗时:5秒”,按钮重新启用。

扩展说明

  • 耗时任务替代:可将 QThread::msleep(500) 替换为实际的耗时操作(如文件读写、网络请求、复杂计算)。
  • 多任务支持:若需执行多个独立任务,可在 Worker 类中添加多个槽函数(如 startTaskAstartTaskB),通过 invokeMethod 按需调用。
  • 线程池:若需管理多个线程,可使用 QThreadPoolQRunnable(适合短任务),但 moveToThread 更适合长时间运行的任务。

这个示例完整展示了 Qt 多线程的核心机制,包括线程创建、任务执行、跨线程通信和安全退出。

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

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

相关文章

从知识图谱到精准决策:基于MCP的招投标货物比对溯源系统实践

前言 从最初对人工智能的懵懂认知&#xff0c;到逐渐踏入Prompt工程的世界&#xff0c;我们一路探索&#xff0c;从私有化部署的实际场景&#xff0c;到对DeepSeek技术的全面解读&#xff0c;再逐步深入到NL2SQL、知识图谱构建、RAG知识库设计&#xff0c;以及ChatBI这些高阶应…

maven如何搭建自己的私服(LINUX版)?

环境准备 安装 JDK &#xff1a;确保系统已安装 JDK 8 或更高版本。可以通过以下命令安装 JDK&#xff1a; 安装 OpenJDK &#xff1a;sudo apt update && sudo apt install openjdk-11-jdk 安装 Oracle JDK &#xff1a;需要添加第三方仓库&#xff0c;例如 WebUpd8 …

armv7 backtrace

ref&#xff1a; ARM Cortex-M3/M4/M7 Hardfault异常分析_arm hardfault-CSDN博客

探索 C++23 的 views::cartesian_product

文章目录 一、背景与动机二、基本概念与语法三、使用示例四、特点与优势五、性能与优化六、与 P2374R4 的关系七、编译器支持八、总结 C23 为我们带来了一系列令人兴奋的新特性&#xff0c;其中 views::cartesian_product 是一个非常实用且强大的功能&#xff0c;它允许我们轻…

SHAP分析!Transformer-BiLSTM组合模型SHAP分析,模型可解释不在发愁!

SHAP分析&#xff01;Transformer-BiLSTM组合模型SHAP分析&#xff0c;模型可解释不在发愁&#xff01; 目录 SHAP分析&#xff01;Transformer-BiLSTM组合模型SHAP分析&#xff0c;模型可解释不在发愁&#xff01;效果一览基本介绍程序设计参考资料 效果一览 基本介绍 基于SH…

牛客周赛 Round 92-题解

牛客周赛 Round 92-题解 A-小红的签到题 code #include<iostream> #include<string> using namespace std; string s; int main() {int n;cin >> n;cout << "a_";for (int i 0; i < n - 2; i )cout << b;return 0; }B-小红的模…

Java设计模式之建造者模式:从入门到精通

1. 建造者模式概述 1.1 定义与核心概念 **建造者模式(Builder Pattern)**是一种创建型设计模式,它将复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。 专业术语解释表: 术语解释产品(Product)最终要构建的复杂对象建造者(Builder)定义创建产品各个…

各类有关NBA数据统计数据集大合集

这些数据我已上传大家在CSDN上直接搜索就可以&#xff01; 一、【2022-2023 NBA球员统计】数据集 关键词: 篮球 描述: 语境 该数据集每场比赛包含2022-2023常规赛NBA球员统计数据。 请注意&#xff0c;由团队更改产生了重复的球员名称。 * [2021-2022 NBA播放器统计]&#…

3、食品包装控制系统 - /自动化与控制组件/food-packaging-control

76个工业组件库示例汇总 食品包装线控制系统 这是一个用于食品包装线控制系统的自定义组件&#xff0c;提供了食品包装生产线的可视化监控与控制界面。组件采用工业风格设计&#xff0c;包含生产流程控制、实时数据监控和逻辑编程三个主要功能区域。 功能特点 工业风格UI设…

NPDP.新产品开发职业认证知识体系NPDP.BOK

第一章 新产品开发战略 1.2 战略及其层级--公司-经营--创新--新产品开发组合-新产品开发项目 “(战略能够)定义与传播一个组织的独特定位&#xff0c;说明应当如何整合组织的资源、技能与能力以获取竞争优势。”(波特&#xff0c;2008) “基于行业定位、机遇和资源,企业为实…

器件(八)—芯片封装中的开尔文源极

首先再次回顾一下MOS到底怎么导通的 在如上的结构中&#xff0c;栅极加压&#xff0c;让N和P-base间形成导电沟道&#xff0c;Vds间加正电压&#xff0c;流到N里的电子依靠这个电压一路飘洋过海&#xff0c;通过Gate给它开辟的沟道&#xff0c;从N到P-base&#xff0c;再从P-ba…

客服系统重构详细计划

# 客服系统重构详细计划 ## 第一阶段&#xff1a;系统分析与准备工作 ### 1. 代码审查和分析 (1-2周) - 全面分析现有代码结构 - 识别代码中的问题和瓶颈 - 理解当前系统的业务逻辑 - 确定可重用的组件 - 制作系统功能清单 ### 2. 技术栈升级准备 (1周) - 升级PHP版本到7…

UNet网络 图像分割模型学习

UNet 由Ronneberger等人于2015年提出&#xff0c;专门针对医学图像分割任务&#xff0c;解决了早期卷积网络在小样本数据下的效率问题和细节丢失难题。 一 核心创新 1.1对称编码器-解码器结构 实现上下文信息与高分辨率细节的双向融合 如图所示&#xff1a;编码器进行了4步&…

【造包工具】【Xcap】精讲Xcap构造分片包(IPv4、ipv6、4G\5G等pcap均可),图解超赞超详细!!!

1. 欢迎大家订阅和关注:精讲网络通信协议(OSI、TCP、IP、UDP、ARP、ICMP、DHCP、HTTP、MQTT、SSL等)知识点,专栏会持续更新中.....敬请期待! 目录 前言 1. XCap工具概念介绍 2. Xcap环境说明 2.1 新建报文组 2.2 导入数据包 2.3 查看报文组 2.4 复制删除报文组 3.…

Qt 界面优化(绘图)

目录 1. 绘图基本概念2. 绘制各种形状2.1 绘制线段2.2 绘制矩形2.3 绘制圆形2.4 绘制文本2.5 设置画笔2.6 设置画刷 3. 绘制图片3.1 绘制简单图片3.2 平移图片3.3 缩放图片3.4 旋转图片 4. 其他设置4.1 移动画家位置4.2 保存/加载画家的状态 5. 特殊的绘图设备5.1 QPixmap5.2 Q…

【计算机视觉】优化MVSNet可微分代价体以提高深度估计精度的关键技术

优化MVSNet可微分代价体以提高深度估计精度的关键技术 1. 代价体基础理论与分析1.1 标准代价体构建1.2 关键问题诊断 2. 特征表示优化2.1 多尺度特征融合2.2 注意力增强匹配 3. 代价体构建优化3.1 自适应深度假设采样3.2 可微分聚合操作改进 4. 正则化与优化策略4.1 多尺度代价…

Python中,async和with结合使用,有什么好处?

在Python的异步编程中&#xff0c;async和with的结合使用&#xff08;即async with&#xff09;为开发者提供了一种优雅且高效的资源管理模式。这种组合不仅简化了异步代码的编写&#xff0c;还显著提升了程序的健壮性和可维护性。以下是其核心优势及典型应用场景的分析&#x…

【金仓数据库征文】金仓数据库:创新驱动,引领数据库行业新未来

一、引言 在数字化转型的时代洪流中&#xff0c;数据已跃升为企业的核心资产&#xff0c;宛如企业运营与发展的 “数字命脉”。从企业日常运营的精细化管理&#xff0c;到战略决策的高瞻远瞩制定&#xff1b;从客户关系管理的深度耕耘&#xff0c;到供应链优化的全面协同&…

Python学习之路(玖)-图像识别的实现

在 Python 中&#xff0c;图像识别对比通常涉及 图像相似度计算 或 目标检测与匹配。-浅看一下就行&#xff0c;具体功能代码&#xff0c;后期会逐步上传资源。 一、技术方案 1. 图像相似度计算 目标&#xff1a;计算两幅图像的相似度。工具&#xff1a; OpenCV&#xff1a;图…

【C语言文件操作详解】fopen 函数全解析 —— 模式参数、使用技巧与重定向的区别

在 C 语言中&#xff0c;文件的读写是一个非常常见的需求。fopen 是标准库中提供的函数&#xff0c;用来打开文件&#xff0c;返回一个文件指针供后续操作使用。本篇博客将详细介绍 fopen 的使用方法、每个参数的含义&#xff0c;以及它与 Shell 中 >、>> 重定向符的联…