QT子線程與主線程的信號槽通信

? ? ? 最近用QT做一個服務器,眾所周知,QT的主線程必須保持暢通,才能刷新UI。所以,網絡通信端采用新開線程的方式。在涉及到使用子線程更新Ui上的控件時遇到了點兒麻煩。網上提供了很多同一線程不同類間采用信號槽通信的方式,但是并不完全適合線程間的信號槽通信,這主要體現在自定義消息的傳遞上。


首先我們看看一般的方式:


testthread.h 文件

[cpp]?view plaincopy
print?
  1. #ifndef?TESTTHREAD_H??
  2. #define?TESTTHREAD_H??
  3. ??
  4. #include?<QThread>??
  5. ??
  6. #include?"msg.h"??
  7. ??
  8. class?TestThread?:?public?QThread??
  9. {??
  10. ????Q_OBJECT??
  11. public:??
  12. ????explicit?TestThread(QObject?*parent?=?0);??
  13. ??
  14. protected:??
  15. ????void?run();??
  16. ??
  17. signals:??
  18. ????void?TestSignal(int);??
  19. ??
  20. private:??
  21. ????Msg?msg;??
  22. };??
  23. ??
  24. #endif?//?TESTTHREAD_H??

testthread.cpp文件

[cpp]?view plaincopy
print?
  1. #include?"testthread.h"??
  2. ??
  3. TestThread::TestThread(QObject?*parent)?:??
  4. ????QThread(parent)??
  5. {??
  6. }??
  7. ??
  8. void?TestThread::run()??
  9. {??
  10. ????//觸發信號??
  11. ????emit?TestSignal(123);??
  12. }??


自己定義的類繼承了QThread類,重寫run函數,然后觸發TestSignal信號。

mainwindow.h

[cpp]?view plaincopy
print?
  1. #ifndef?MAINWINDOW_H??
  2. #define?MAINWINDOW_H??
  3. ??
  4. #include?<QMainWindow>??
  5. ??
  6. #include?"testthread.h"??
  7. ??
  8. namespace?Ui?{??
  9. class?MainWindow;??
  10. }??
  11. ??
  12. class?MainWindow?:?public?QMainWindow??
  13. {??
  14. ????Q_OBJECT??
  15. ??
  16. public:??
  17. ????explicit?MainWindow(QWidget?*parent?=?0);??
  18. ????~MainWindow();??
  19. ??
  20. private?slots:??
  21. ????void?DisplayMsg(int);??
  22. ??
  23. private:??
  24. ????Ui::MainWindow?*ui;??
  25. ????TestThread?*t;??
  26. };??
  27. ??
  28. #endif?//?MAINWINDOW_H??

mainwindow.cpp

[cpp]?view plaincopy
print?
  1. #include?"mainwindow.h"??
  2. #include?"ui_mainwindow.h"??
  3. ??
  4. MainWindow::MainWindow(QWidget?*parent)?:??
  5. ????QMainWindow(parent),??
  6. ????ui(new?Ui::MainWindow)??
  7. {??
  8. ????ui->setupUi(this);??
  9. ??
  10. ????//進行connect前必須實例化??
  11. ????t?=?new?TestThread();?????
  12. ??
  13. ????connect(t,?SIGNAL(TestSignal(int)),?this,?SLOT(DisplayMsg(int)));??
  14. ??
  15. ????//執行子線程??
  16. ????t->start();???
  17. }??
  18. ??
  19. void?MainWindow::DisplayMsg(int?a)??
  20. {??
  21. ????ui->textBrowser->append(QString::number(a));??
  22. }??
  23. ??
  24. MainWindow::~MainWindow()??
  25. {??
  26. ????delete?ui;??
  27. }??

Mainwindow里面連接信號槽,并且將收到的int參數顯示在界面上。


運行效果



下面我們對程序進行一些簡單,修改,使得它傳輸我們的自定義消息。


testthread.h 文件

[cpp]?view plaincopy
print?
  1. #ifndef?TESTTHREAD_H??
  2. #define?TESTTHREAD_H??
  3. ??
  4. #include?<QThread>??
  5. ??
  6. #include?"msg.h"??
  7. ??
  8. class?TestThread?:?public?QThread??
  9. {??
  10. ????Q_OBJECT??
  11. public:??
  12. ????explicit?TestThread(QObject?*parent?=?0);??
  13. ????Msg?msg;??
  14. ??
  15. protected:??
  16. ????void?run();??
  17. ??
  18. signals:??
  19. ????void?TestSignal(Msg);???//Msg!!!??
  20. };??
  21. ??
  22. #endif?//?TESTTHREAD_H??

testthread.h 文件

[cpp]?view plaincopy
print?
  1. #include?"testthread.h"??
  2. ??
  3. TestThread::TestThread(QObject?*parent)?:??
  4. ????QThread(parent)??
  5. {??
  6. }??
  7. ??
  8. void?TestThread::run()??
  9. {??
  10. ????msg.int_info?=?999;??
  11. ????msg.str_info?=?"Hello?Main?Thread!";??
  12. ????//觸發信號??
  13. ????emit?TestSignal(msg);??
  14. }??

mainwindow.h 文件

[cpp]?view plaincopy
print?
  1. #ifndef?MAINWINDOW_H??
  2. #define?MAINWINDOW_H??
  3. ??
  4. #include?<QMainWindow>??
  5. ??
  6. #include?"testthread.h"??
  7. #include?"msg.h"??
  8. ??
  9. namespace?Ui?{??
  10. class?MainWindow;??
  11. }??
  12. ??
  13. class?MainWindow?:?public?QMainWindow??
  14. {??
  15. ????Q_OBJECT??
  16. ??
  17. public:??
  18. ????explicit?MainWindow(QWidget?*parent?=?0);??
  19. ????~MainWindow();??
  20. ??
  21. private?slots:??
  22. ????void?DisplayMsg(Msg);???//Msg!!!??
  23. ??
  24. private:??
  25. ????Ui::MainWindow?*ui;??
  26. ????TestThread?*t;??
  27. };??
  28. ??
  29. #endif?//?MAINWINDOW_H??

mainwindow.cpp 文件

[cpp]?view plaincopy
print?
  1. #include?"mainwindow.h"??
  2. #include?"ui_mainwindow.h"??
  3. ??
  4. MainWindow::MainWindow(QWidget?*parent)?:??
  5. ????QMainWindow(parent),??
  6. ????ui(new?Ui::MainWindow)??
  7. {??
  8. ????ui->setupUi(this);??
  9. ??
  10. ????//進行connect前必須實例化??
  11. ????t?=?new?TestThread();??
  12. ??
  13. ????//Msg!!!??
  14. ????connect(t,?SIGNAL(TestSignal(Msg)),?this,?SLOT(DisplayMsg(Msg)));??
  15. ??
  16. ????//執行子線程??
  17. ????t->start();??
  18. }??
  19. ??
  20. void?MainWindow::DisplayMsg(Msg?msg)??
  21. {??
  22. ????ui->textBrowser->append(QString::number(msg.int_info));??
  23. ????ui->textBrowser->append(msg.str_info);??
  24. }??
  25. ??
  26. MainWindow::~MainWindow()??
  27. {??
  28. ????delete?ui;??
  29. }??

此時再進行編譯,能夠通過,但是Qt Creator會有提示

[cpp]?view plaincopy
print?
  1. QObject::connect:?Cannot?queue?arguments?of?type?'Msg'??
  2. (Make?sure?'Msg'?is?registered?using?qRegisterMetaType().)??

并且運行程序,不會有任何反應。


mainwindow.cpp文件 改動為

[cpp]?view plaincopy
print?
  1. ui->setupUi(this);??
  2. ??
  3. qRegisterMetaType<Msg>("Msg");??

此時能夠正常運行




說明:

在線程間使用信號槽進行通信時,需要注意必須使用元數據類型

Qt內生的元數據類型,如int double QString 等

如果要用自己定義的數據類型,需要在connect前將其注冊為元數據類型。形式見代碼。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/383260.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/383260.shtml
英文地址,請注明出處:http://en.pswp.cn/news/383260.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ubuntu14.04 通過PPA 安裝ffmpeg

去ffmpeg的官網可以獲取到最新的PPA信息 http://www.ffmpeg.org/download.html 根據系統選擇對應的PPA 然后執行以下語句&#xff1a; sudo add-apt-repository ppa:mc3man/trusty-media sudo apt-get updatesudo apt-get install ffmpeg 如果在安裝過程中發生了錯誤&#…

c++中的函數適配器

函數適配器 函數適配器概念 STL中定義了大量的函數對象&#xff0c;但是有時候需要對函數返回值進行進一步的簡單計算&#xff0c;或者填上多余的參數&#xff0c;不能直接代入算法&#xff0c;函數適配器實現了這一功能&#xff0c;將一種函數對象轉化為另一種符合要求的函數…

c++中STL的常用算法---2(遍歷算法,查找算法)

算法概述 算法主要由頭文件組成是所有STL頭文件中最大的一個&#xff0c;其中常用的功能涉及到比較&#xff0c;交換&#xff0c;查找&#xff0c;遍歷&#xff0c;復制&#xff0c;修改&#xff0c;反轉&#xff0c;排序&#xff0c;合并等體積很小&#xff0c;只包括在幾個序…

c++中的STL的常用算法---3(排序算法,拷貝和替換算法,算術生成算法,集合算法)

排序算法 merge() 以下是排序和通用算法&#xff1a;提供元素排序策略 merge: 合并兩個有序序列&#xff0c;存放到另一個序列。 #include<iostream>using namespace std; #include<algorithm> #include<vector>void test01() {vector<int >v1;vecto…

c++中STL實現演講比賽流程

演講比賽流程 1&#xff09;某市舉行一場演講比賽&#xff0c;共有 24 個人參加&#xff0c;按參加順序設置參賽號。比賽共三輪&#xff0c;前兩 輪為淘汰賽&#xff0c;第三輪為決賽。 2&#xff09;比賽方式&#xff1a;分組比賽 第一輪分為 4 個小組&#xff0c;根據參賽號…

c++實現貪吃蛇

游戲中的實現元素 游戲中元素分為&#xff1a;墻壁&#xff0c;蛇&#xff0c;事物以及蛇的可行區域和右側的版本號和游戲玩法提示 墻壁 *號表示&#xff0c;代表一個區域范圍&#xff0c;也就是蛇的可移動區域&#xff0c;蛇如果碰到墻壁視為死亡&#xff0c; 蛇 分為蛇頭&a…

Linux系統編程--1(進程和程序,CPU和MMU,PCB,進程狀態)

進程相關概念 程序和進程 程序&#xff1a;是指編譯好的二進制文件&#xff0c;在磁盤上&#xff0c;不占用系統資源(cpu、內存、打開的文件、設備、鎖…) 進程&#xff1a;是一個抽象的概念&#xff0c;與操作系統原理聯系緊密。進程是活躍的程序&#xff08;程序員角度&…

C++STL學習

1. STL介紹標準模板庫STL是當今每個從事C編程的人需要掌握的技術&#xff0c;所有很有必要總結下本文將介紹STL并探討它的三個主要概念&#xff1a;容器、迭代器、算法。STL的最大特點就是&#xff1a;數據結構和算法的分離&#xff0c;非面向對象本質。訪問對象是通過象指針一…

Linux系統編程--2(環境變量,進程控制)

環境變量 環境變量 是指在操作系統中用來指定操作系統運行環境的一些參數 每個人用電腦的習慣不一樣&#xff0c;比如一般把文件放到磁盤&#xff0c;怎么管理文件&#xff0c;用什么編譯器&#xff0c;所以&#xff0c;環境變量就是根據每個人使用操作系統的習慣來規定一些參…

STL-vector

STL學習之二 序列容器&#xff08;vector&#xff09;一、C標準模板庫提供了三種序列容器&#xff1a;vector、list、deque。類模板vector和deque都以數組為基礎&#xff0c;類模板list實現了鏈表的數據結構。STL中最流行的是類模板vector&#xff0c;它是一種更健壯的數據類型…

套接字編程--1(UDP協議編程,端口號,傳輸層協議,網絡字節序)

傳輸層的協議&#xff1a; ip地址&#xff1a; 在網絡中唯一標識一臺主機 IPV4&#xff1a;uint32_t DHCP NATIPV6 : uint8_t addr[16] —向前并不兼容IPV4 每一條數據都必須包含源地址和目的地址&#xff1a;因為每條網絡中的數據都必須確定是從那個主機來到那個主機去 端…

ARP簡單介紹

ARP簡介 ARP&#xff08;Address Resolution Protocol&#xff09;用于將IP地址解析為MAC地址 1. ARP地址解析的必要性 IP地址不能直接用來進行通信&#xff0c;因為網絡設備只能識別MAC地址。IP地址只是主機在網絡層中的地址&#xff0c;如果要將網絡層中傳送的數據報交給…

Linux系統編程--3(exec 函數族,僵尸進程和孤兒進程,wait和wait_pid回收子進程)

exec 函數族 fork 創建子進程后執行的是和父進程相同的程序&#xff08;但有可能執行不同的代碼分支&#xff09; &#xff0c;子進程往往要調用一種 exec 函數以執行另一個程序。當進程調用一種 exec 函數時&#xff0c;該進程的用戶空間代碼和數據完全被新程序替換&#xff…

交換機MAC地址學習和轉發數據幀的原理

1 &#xff1a;交換機 MAC 地址學習在交換機初始化的&#xff0c;也就是剛啟動的時候&#xff0c;交換機的MAC地址表是沒有任何MAC地址和端口的映射條目的 當PCA要想和PCC&#xff0c;PCB,PCD進行通信時&#xff0c;當該二層數據幀通過端口E1/0/1發送到交換機上時&#xff0c…

Linux系統編程---4(進程間通信IPC,管道)

進程間通信目的 數據傳輸&#xff1a;一個進程需要將它的數據發送給另一個進程資源共享&#xff1a;多個進程之間共享同樣的資源。通知事件&#xff1a;一個進程需要向另一個或一組進程發送消息&#xff0c;通知它&#xff08;它們&#xff09;發生了某種事件&#xff08;如進…

沖突域 廣播域簡單解釋

網絡互連設備可以將網絡劃分為不同的沖突域、廣播域。但是&#xff0c;由于不同的網絡互連設備可能工作在OSI模型的不同層次上。因此&#xff0c;它們劃分沖突域、廣播域的效果也就各不相同。如中繼器工作在物理層&#xff0c;網橋和交換機工作在數據鏈路層&#xff0c;路由器工…

Linux系統編程---5(共享存儲映射,存儲映射I/O,mmap函數,父子進程間通信,匿名映射)

共享存儲映射 文件進程間通信 使用文件也可以完成 IPC&#xff0c;理論依據是&#xff0c;fork 后&#xff0c;父子進程共享文件描述符。也就共享打開的文件。 編程&#xff1a;父子進程共享打開的文件。借助文件進行進程間通信。 測試代碼 /*** 父子進程共享打開的文件描述…

變量的存取

一、預備知識―程序的內存分配 一個由c/C編譯的程序占用的內存分為以下幾個部分 1、棧區&#xff08;stack&#xff09;― 由編譯器自動分配釋放 &#xff0c;存放函數的參數值&#xff0c;局部變量的值等。其操作方式類似于數據結構中的棧。 2、堆區&#xff08;heap&#xff…

Linux下文件的多進程拷貝

大文件拷貝 假設有一個超大文件&#xff0c;需對其完成拷貝工作。為提高效率&#xff0c;可采用多進程并行拷貝的方法來實現。假設文件 大小為 len&#xff0c;共有 n 個進程對該文件進行拷貝。那每個進程拷貝的字節數應為 len/n。但未必一定能整除&#xff0c;我們可 以選擇讓…