实现步骤

  1. 创建工作类 (Worker):在工作线程中处理数据的对象。

  2. 创建线程对象 (QThread):用来托管工作对象。

  3. 连接信号槽

    • 主线程 -> 工作线程:连接一个主窗口发出的信号工作对象的槽,用于传递数据。

    • 工作线程 -> 主线程:连接工作对象发出的信号主窗口的槽,用于返回结果、更新UI。

  4. 移动工作对象:将工作对象移动到新线程。

  5. 启动线程:启动线程的事件循环。

  6. 按钮点击:在按钮点击的槽函数中,发射那个用于传递数据的信号。

完整代码示例

1. 工作类 (worker.h)

// worker.h
#ifndef WORKER_H
#define WORKER_H#include <QObject>
#include <QString>
#include <QDebug>
#include <QThread>class Worker : public QObject
{Q_OBJECTpublic:explicit Worker(QObject *parent = nullptr) : QObject(parent) {}public slots:// 这个槽函数专门用来接收主线程发来的数据并进行处理void handleDataFromMainThread(const QString &data) {qDebug() << "工作线程ID:" << QThread::currentThreadId();qDebug() << "收到主线程发来的数据:" << data;// 模拟一个耗时的数据处理过程QString result;for (int i = 0; i < data.length(); ++i) {QThread::msleep(200); // 模拟处理每个字符需要时间result.prepend(data[i]); // 做一个简单的反转操作作为处理示例emit progress(i+1, data.length()); // 发送处理进度}// 处理完成,发射信号将结果发回主线程emit dataProcessed(result);}signals:// 处理进度信号 (当前进度, 总数)void progress(int current, int total);// 处理完成信号 (结果)void dataProcessed(const QString &result);
};#endif // WORKER_H

2. 主窗口头文件 (mainwindow.h)

// mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();// 新增一个信号,用于向工作线程发送数据
signals:void sendDataToWorker(const QString &data);private slots:// 按钮点击的槽函数void on_pushButtonStart_clicked();// 接收工作线程发回的信号的槽函数void updateProgress(int current, int total);void handleResult(const QString &result);private:Ui::MainWindow *ui;QThread *workerThread;
};#endif // MAINWINDOW_H

3. 主窗口实现 (mainwindow.cpp) - 核心

// mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "worker.h" // 包含工作类头文件
#include <QThread>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow), workerThread(new QThread(this)) // 线程对象的父对象是主窗口,生命周期由其管理
{ui->setupUi(this);// 创建工作者对象,此时它还在主线程Worker *worker = new Worker;// !!! 关键步骤:将工作者对象移动到新线程 !!!worker->moveToThread(workerThread);// !!! 核心连接:主线程 -> 工作线程 !!!// 当主窗口发射 sendDataToWorker 信号时, worker 的 handleDataFromMainThread 槽函数会被调用// 因为 worker 已移动到新线程,这个连接会自动使用 QueuedConnection,保证线程安全connect(this, &MainWindow::sendDataToWorker, worker, &Worker::handleDataFromMainThread);// 连接:工作线程 -> 主线程 (用于更新UI)connect(worker, &Worker::progress, this, &MainWindow::updateProgress);connect(worker, &Worker::dataProcessed, this, &MainWindow::handleResult);// 连接线程结束信号,用于自动清理对象connect(workerThread, &QThread::finished, worker, &QObject::deleteLater);connect(workerThread, &QThread::finished, workerThread, &QObject::deleteLater);// 启动线程(启动事件循环)workerThread->start();// 初始化UIui->progressBar->setValue(0);
}MainWindow::~MainWindow()
{// 优雅退出线程if (workerThread && workerThread->isRunning()) {workerThread->quit();workerThread->wait();}delete ui;
}// 按钮点击事件
void MainWindow::on_pushButtonStart_clicked()
{QString inputData = ui->lineEditInput->text();if (inputData.isEmpty()) {return;}// 禁用按钮,防止重复点击ui->pushButtonStart->setEnabled(false);ui->progressBar->setValue(0);// !!! 核心操作:发射信号,将数据发送到工作线程 !!!qDebug() << "主线程ID:" << QThread::currentThreadId() << ",发射信号,数据:" << inputData;emit sendDataToWorker(inputData);
}// 更新进度条
void MainWindow::updateProgress(int current, int total)
{int percent = (current * 100) / total;ui->progressBar->setValue(percent);ui->labelStatus->setText(QString("处理中: %1/%2").arg(current).arg(total));
}// 显示处理结果
void MainWindow::handleResult(const QString &result)
{ui->textEditResult->setText(result);ui->labelStatus->setText("处理完成!");ui->pushButtonStart->setEnabled(true); // 重新启用按钮
}

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

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

相关文章

【CV 目标检测】Fast RCNN模型①——与R-CNN区别

3.Fast RCNN模型 相比于R-CNN&#xff0c;Fast RCNN模型主要在以下三个方面进行了改进&#xff1a; 提高训练和预测速度 R-CNN首先从测试图中提取2000个候选区域&#xff0c;然后将这2000个候选区域分别输入到预训练好的CNN中提取特征。由于候选区域有大量的重叠&#xff0c;这…

Zookeeper学习

要精通 ZooKeeper&#xff0c;需要掌握其核心原理、数据模型、分布式协调机制、典型应用场景、运维管理与性能调优等方面的知识。以下是系统化的知识体系&#xff1a;✅ 一、ZooKeeper 基础原理ZooKeeper 是什么 分布式协调服务&#xff0c;提供一致性、高可用的元数据管理核心…

用TestComplete打造高效CI/CD测试流程

传统的UI测试往往受限于图形界面渲染&#xff0c;导致执行速度慢、资源占用高&#xff0c;难以适应持续集成/持续交付&#xff08;CI/CD&#xff09;管道的需求。自动化UI测试平台TestComplete的智能质量附加组件通过无头测试技术&#xff0c;为开发团队提供了一种更高效、更可…

C++ 浅拷贝 和深拷贝的知识点讲解

好问题 &#x1f44d;&#xff0c;这个就是理解 delete 的关键前置知识。 我从 C语言基础 出发&#xff0c;像教科书一样&#xff0c;从零讲给你听。1. 什么是“拷贝”&#xff1f; 在 C 中&#xff0c;当你有一个对象 A&#xff0c;然后写&#xff1a; Device_Info a; Device…

Arkts加载网页url的pdf发票黑屏问题

使用模拟器会闪退&#xff0c;连接真机预览正常import { HMRouter, HMRouterMgr, HMParamType, HMPageParam } from "hadss/hmrouter"; import { BaseTitle, RouterConstants } from "commonlib"; import { webview } from kit.ArkWeb; import { PDFView }…

使用 mongosh 设置 MongoDB 账号密码

可以使用 mongosh(MongoDB 6.0+ 的现代Shell)来设置账号密码。mongosh 是官方推荐的新一代MongoDB Shell工具,替代了传统的 mongo 命令。 【本人博文提到的ip均为随机生成的,不是实际的ip,仅供参考,如有雷同,纯属巧合】 使用 mongosh 设置 MongoDB 账号密码 1. 首先连…

HTML+CSS:浮动详解

在HTMLCSS布局中&#xff0c;浮动&#xff08;float&#xff09; 是一种经典的布局技术&#xff0c;用于控制元素在页面中的排列方式。它最初设计用于实现文字环绕图片的效果&#xff0c;后来被广泛用于复杂布局&#xff0c;但随着Flexbox和Grid的兴起&#xff0c;其使用场景有…

GPIO初始化及调用

下面把 HAL 库 和 标准外设库&#xff08;SPL&#xff09; 初始化 GPIO 点亮/熄灭 LED 的完整步骤、示例代码和常用 API 逐一说清楚。用例默认 PC13 接 LED&#xff08;蓝板常见&#xff1b;低电平点亮&#xff0c;高电平熄灭——若板子相反&#xff0c;只把写 1/0 对调即可&am…

【GPT入门】第48课 LlamaFacotory 合并原模型与LoRA模型

【GPT入门】第48课 LlamaFacotory 合并原模型与LoRA模型1.合并原模型与LoRA训练的增量模型2. 测试模型1.合并原模型与LoRA训练的增量模型 llamafactory-cli webui 执行合并 合并后模型大小 (base) rootautodl-container-b4b04ea4f2-b5ee47d1:~# du -sh /root/autodl-tmp/mod…

Python爬虫实战:研究tumblr,构建博客平台数据采集分析系统

1. 引言 1.1 研究背景 在信息爆炸的时代,社交媒体平台已成为人们获取信息、表达观点和进行社交互动的主要渠道。这些平台上积累的海量数据包含了用户偏好、社会趋势、文化现象等丰富信息,对学术研究、市场分析、产品开发等领域具有重要价值。 Tumblr 作为一个综合性的轻博客…

集成算法学习总结

一、集成学习基础认知 核心思想&#xff1a;集成学习&#xff08;ensemble learning&#xff09;通过构建并结合多个个体学习器来完成学习任务&#xff0c;类似于 “多个专家共同决策”&#xff0c;通常比单个学习器的性能更优。其核心逻辑是利用多个学习器的优势互补&#xff…

线程安全的产生以及解决方案

线程安全原子性&#xff08;Atomicity&#xff09;、可见性&#xff08;Visibility&#xff09;、有序性&#xff08;Ordering&#xff09; 是保证线程安全的三大核心要素 —— 线程安全问题的本质&#xff0c;几乎都是这三个特性中的一个或多个被破坏导致的。操作不会被 “中途…

Spring Cloud Netflix学习笔记01

文章目录前言一、微服务概述什么是微服务&#xff1f;微服务与微服务架构微服务优缺点优点缺点微服务技术栈有那些&#xff1f;二.SpringCloud入门概述SpringCloud是什么&#xff1f;SpringCloud和SpringBoot的关系Dubbo 和 SpringCloud技术选型总结SpringCloud能干嘛&#xff…

专题:2025母婴行业消费洞察与分龄营养趋势报告|附40 +份报告PDF、交互图表数据汇总下载

原文链接&#xff1a;https://tecdat.cn/?p43654 当95后妈妈拿着计算器对比DHA纯度&#xff0c;当爸爸们为“防红屁屁纸尿裤”货比三家&#xff0c;母婴行业的风向早就变了。从“一把奶粉喂到3岁”到“按月龄定制营养包”&#xff0c;从“进口就好”到“看专利数据下单”&…

redhat6/centos6 配置yum源

由于RHEL6/centos6系统官方早就停止通知维护了&#xff0c;公司的开发服务器有比较老&#xff0c;发现竟然scp都没有装。。。今天配置个本地yum源&#xff0c;安装一下常规软件和开发环境比较简单&#xff0c;直接上代码1.上传一个centos6的iso文件CentOS-6.5-x86_64-bin-DVD1.…

day31 SQLITE

数据库相关函数数据库创建int sqlite3_open( const char *filename, sqlite3 **ppDb);功能&#xff1a;打开数据库&#xff0c;不存在则创建参数&#xff1a;const char *filename 数据库名sqlite3 **ppDb 二级指针&#xff0c;传出ppDb数据库的一级指…

嵌入式-SPI番外之按钮驱动程序的编写-Day15

目录 一、按钮简单操作回忆 二、按钮新操作实现 &#xff08;1&#xff09;按钮的点击实现灯亮/灭 ①连接电路 ②初始化板载LED和按钮 ③按钮程序的基本原理&#xff08;核心仍为0亮/1灭&#xff09; ④按钮消抖的原理 三、按钮封装的操作-点击&#xff0c;双击&#xf…

星域智链科技:用科技点亮生活,以 AI 拓展无限可能

星域智链科技&#xff08;东莞市&#xff09;有限公司简介 星域智链科技&#xff08;东莞市&#xff09;有限公司&#xff0c;理念是 让科技便利生活、丰富生活&#xff0c;专注于科技、AI领域。 全场景 GPS 定位器 —— 精准追踪&#xff0c;守护安全&#xff0c;适用于车辆…

国内代理IP在SEO行业中的应用

随着互联网的快速发展&#xff0c;SEO&#xff08;搜索引擎优化&#xff09;已经成为了数字营销的重要组成部分。无论是企业还是个人站长&#xff0c;都希望通过SEO提升自己网站的排名和流量。然而&#xff0c;随着竞争的激烈&#xff0c;传统的SEO优化手段已经逐渐显现出局限性…

Linux + arm 内存屏障

ARM 硬件层的屏障指令DMB (Data Memory Barrier)&#xff1a;保证在它之前的内存访问&#xff08;符合给定域/类型&#xff09;在它之后的内存访问之前对可见性排序。常用域&#xff1a;ish&#xff08;Inner Shareable&#xff09;&#xff0c;sy&#xff08;system-wide&…