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.pswp.cn/news/905087.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/905087.shtml
英文地址,請注明出處:http://en.pswp.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 中 >、>> 重定向符的聯…