qt线程通信(通过信号触发来传递参数)

标签: qt开发 线程 通信 qt学习 socket
893人阅读 评论(0) 收藏 举报
分类:
最近用QT做一个服务器,众所周知,QT的主线程必须保持畅通,才能刷新UI。所以,网络通信端采用新开线程的方式。在涉及到使用子线程更新Ui上的控件时遇到了点儿麻烦。网上提供了很多同一线程不同类间采用信号槽通信的方式,但是并不完全适合线程间的信号槽通信,这主要体现在自定义消息的传递上。


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


testthread.h 文件

  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文件
  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

  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
  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 文件

  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 文件
  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 文件

  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 文件
  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会有提示
  1. QObject::connect: Cannot queue arguments of type 'Msg'  
  2. (Make sure 'Msg' is registered using qRegisterMetaType().)  

并且运行程序,不会有任何反应。


mainwindow.cpp文件 改动为

  1. ui->setupUi(this);  
  2.   
  3. qRegisterMetaType<Msg>("Msg");  

此时能够正常运行




说明:

在线程间使用信号槽进行通信时,需要注意必须使用元数据类型

Qt内生的元数据类型,如int double QString 等

如果要用自己定义的数据类型,需要在connect前将其注册为元数据类型。形式见代码。


转载来自blog.csdn.net/jmy5945hh/article/details/34796359/ 


这个例子是主线程和子线程的,子线程与子线程之间通信呢?

connect 的 第一个参数 和第三个参数改成监听对象

 connect(t, SIGNAL(TestSignal(Msg)), this, SLOT(DisplayMsg(Msg)));


 

以上的this就是主线程响应,把this改成要监听的另一个线程对象就好了(QT多么健壮 友好  强大)

前提是全部的线程都要在主线程里面实例化new


今天实现的一个结构提参数通过Singal传递的例子。。 那个实现是子线程与GUI子线程的参数进行传递  通过mainWindow来做中转。具体是把用户输入的数据进行复杂计算,计算交给线程做,GUI负责用户输入输出


线程头文件

ABFThread.h


public:

    struct G_ABFTableSrcUnit
    {
        int a;
        int b;
        int c;
        float d;
        float e;
        unsigned int f;
        float Gg;
    
        QString waveformTypel;
    };

public slots:

    void parameterPassing(abfThread::G_ABFTableSrcUnit); //线程自己调用自己的结构体。。。必须这么写不然主线程会报错的  错误是参数内容不一样

ABFThread.cpp

void abfThread::parameterPassing(abfThread::G_ABFTableSrcUnit)
{

}

GUI线程

radarControl.h

#include "abfThread"

private:
    Ui::radarControl *ui;

    abfThread::G_ABFTableSrcUnit mst_abfSrcUnit;


signals:
    void sendString(abfThread::G_ABFTableSrcUnit);


radarControl.cpp

按下按钮就发射信号

void radarControl::on_pushButton_clicked()
{
    emit sendString(mst_abfSrcUnit);
}

mainWindow.h

#include "abfThread.h"
#include "radarControl.h"


mainWindow.cpp


radarInterface = new radarControl();
m_ABFThread = new QThread();
    m_ABF = new abfThread();
    m_ABF->moveToThread(m_ABFThread);
    m_ABFThread->start();

    qRegisterMetaType<abfThread::G_ABFTableSrcUnit>("abfThread::G_ABFTableSrcUnit");
    connect(radarInterface,SIGNAL(sendString(abfThread::G_ABFTableSrcUnit)),m_ABF,SLOT(parameterPassing(abfThread::G_ABFTableSrcUnit)));
//除了注册结构体外  还要保证传递的参数写法要一样  这就是为什么 前面线程自己定义的结构体自己调用自己的原因了






查看评论

Qt基础与Qt on Android入门

本课程起始于基础的开发环境搭建和Qt Creator快速介绍,帮助初学者入门;着力于Qt的内在机制,由浅入深介绍信号与槽、Qt模板库、事件、文件处理、XML、网络、多线程、各种GUI控件、布局管理器等各种Qt基础主题(这些主题可同时在Qt桌面编程和Android平台上使用),同时辅以简洁有效有针对性的实例程序(每个示例程序都可以在 Android 平台上运行)。
  • 2014年11月27日 10:53

QT线程中如何修改界面?(QT往线程里传参数)

我创建了一个网络监视线程,打算将这个线程分析的数据追加显示到一个 QTextEdit 控件上。 每当在这个线程中调用  QTextEdit->append (psDtata); 的时候,程序就出错误...
  • dx01259
  • dx01259
  • 2015-03-18 11:08:49
  • 1794

QT多线程简单实现及变量传递

QT自定义信号与槽 自定义信号与槽 Qt多线程简单实现 多线程间变量传递
  • hyw11002233
  • hyw11002233
  • 2016-11-15 10:49:35
  • 5102

qt下利用connect跨线程发送数据

最近在做某厂家的nvr插件开发,涉及到qt下多线程的开发,具体的思路大概这样,每一个线程对应一个nvr,但是每一个线程里又存在另外一个线程(即nvr的回调函数),因为回调函数是静态函数,所以在该函数里...
  • sanmingshen
  • sanmingshen
  • 2014-01-17 14:13:10
  • 2025

Qt多线程之间传递参数

在主线程中进行如下操作: connect(this, SIGNAL(ReceiveThread(void*,int,int)), receiveInfo, SLOT(doReceiveTh(...
  • qq_32693119
  • qq_32693119
  • 2018-03-01 14:18:47
  • 48

信号槽如何传递参数(或带参数的信号槽)

信号槽如何传递参数(或带参数的信号槽) 利用Qt进行程序开发时,有时需要信号槽来完成参数传递。带参数的信号槽在使用时,有几点需要注意的地方,下面结合实例进行介绍。 第一点:当信号与槽函数的参数数量相同...
  • lyc_daniel
  • lyc_daniel
  • 2013-09-26 14:30:51
  • 23900

QT信号槽传递参数技巧

信号槽如何传递参数(或带参数的信号槽) 利用Qt进行程序开发时,有时需要信号槽来完成参数传递。带参数的信号槽在使用时,有几点需要注意的地方,下面结合实例进行介绍。 第一点:当信号与槽函数的参数数量...
  • you_shou
  • you_shou
  • 2016-03-24 11:09:01
  • 4434

qt的Qt::ConnectionType详细以及信号参数传递

信号和槽的同步异步 这个可以通过connect的最后一个参数指定。 connect的时候最后一个参数解释。并不需要知道胡乱指定参数会触发什么状况。只需要知道在什么状况下指定什么样的参数就可以 ...
  • groundhappy
  • groundhappy
  • 2016-04-27 10:52:42
  • 1702

QT多窗口间传值---信号槽方法

在写程序时,难免会碰到多窗体之间进行传值的问题。依照自己的理解,我把多窗体传值的可以使用的方法归纳如下:       1.使用QT中的Signal&Slot机制进行传值;       2....
  • lywzgzl
  • lywzgzl
  • 2014-11-13 19:38:33
  • 6849

QT窗体间传值总结之Signal&Slot

在写程序时,难免会碰到多窗体之间进行传值的问题。依照自己的理解,我把多窗体传值的可以使用的方法归纳如下:       1.使用QT中的Signal&Slot机制进行传值;       2.使用全局...
  • hanxing0
  • hanxing0
  • 2013-06-13 16:18:25
  • 21024
    个人资料
    等级:
    访问量: 5287
    积分: 150
    排名: 111万+
    文章分类
    文章存档