Qt 中最經典、最常用的多線程通信場景

實現步驟

  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&…