[转]QT子线程与主线程的信号槽通信-亲测可用!

摘要:
近用QT做一个服务器,众所周知,QT的主线程必须保持畅通,才能刷新UI。在涉及到使用子线程更新Ui上的控件时遇到了点儿麻烦。网上提供了很多同一线程不同类间采用信号槽通信的方式,但是并不完全适合线程间的信号槽通信,这主要体现在自定义消息的传递上。mainwindow.h#ifndefMAINWINDOW_H#defineMAINWINDOW_H#include#include"testthread.h"namespaceUi{classMainWindow;}classMainWindow:publicQMainWindow{Q_OBJECTpublic:explicitMainWindow;~MainWindow();privateslots:voidDisplayMsg;private:Ui::MainWindow*ui;TestThread*t;};#endif//MAINWINDOW_Hmainwindow.cpp#include"mainwindow.h"#include"ui_mainwindow.h"MainWindow::MainWindow:QMainWindow,ui{ui-˃setupUi;//进行connect前必须实例化t=newTestThread();connect;//执行子线程t-˃start();}voidMainWindow::DisplayMsg{ui-˃textBrowser-˃append;}MainWindow::~MainWindow(){deleteui;}Mainwindow里面连接信号槽,并且将收到的int参数显示在界面上。以上测试用例,经过本人亲测可用!!!!

近用QT做一个服务器,众所周知,QT的主线程必须保持畅通,才能刷新UI。所以,网络通信端采用新开线程的方式。在涉及到使用子线程更新Ui上的控件时遇到了点儿麻烦。网上提供了很多同一线程不同类间采用信号槽通信的方式,但是并不完全适合线程间的信号槽通信,这主要体现在自定义消息的传递上。

首先我们看看一般的方式:
利用信号-槽发送Qt内置的元数据类型
testthread.h 文件

#ifndef TESTTHREAD_H
#define TESTTHREAD_H
#include <QThread>
#include "msg.h"
class TestThread : publicQThread
{
    Q_OBJECT
public:
    explicit TestThread(QObject *parent = 0);
protected:
    voidrun();
signals:
    void TestSignal(int);
private:
    Msg msg;
};
#endif //TESTTHREAD_H

testthread.cpp文件

#include "testthread.h"
TestThread::TestThread(QObject *parent) :
    QThread(parent)
{
}
voidTestThread::run()
{
    //触发信号
    emit TestSignal(123);
}

自己定义的类继承了QThread类,重写run函数,然后触发TestSignal信号。

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "testthread.h"
namespaceUi {
classMainWindow;
}
class MainWindow : publicQMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
privateslots:
    void DisplayMsg(int);
private:
    Ui::MainWindow *ui;
    TestThread *t;
};
#endif //MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(newUi::MainWindow)
{
    ui->setupUi(this);
    //进行connect前必须实例化
    t = newTestThread();   
    connect(t, SIGNAL(TestSignal(int)), this, SLOT(DisplayMsg(int)));
    //执行子线程
    t->start(); 
}
void MainWindow::DisplayMsg(inta)
{
    ui->textBrowser->append(QString::number(a));
}
MainWindow::~MainWindow()
{
    deleteui;
}

Mainwindow里面连接信号槽,并且将收到的int参数显示在界面上。

运行效果:

[转]QT子线程与主线程的信号槽通信-亲测可用!第1张

利用信号-槽发送自定义消息

下面我们对程序进行一些简单,修改,使得它传输我们的自定义消息。

testthread.h 文件

#ifndef TESTTHREAD_H
#define TESTTHREAD_H
#include <QThread>
#include "msg.h"
class TestThread : publicQThread
{
    Q_OBJECT
public:
    explicit TestThread(QObject *parent = 0);
    Msg msg;
protected:
    voidrun();
signals:
    void TestSignal(Msg);   //Msg!!!
};
#endif //TESTTHREAD_H

testthread.h 文件

#include "testthread.h"
TestThread::TestThread(QObject *parent) :
    QThread(parent)
{
}
voidTestThread::run()
{
    msg.int_info = 999;
    msg.str_info = "Hello Main Thread!";
    //触发信号
emit TestSignal(msg);
}

mainwindow.h 文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "testthread.h"
#include "msg.h"
namespaceUi {
classMainWindow;
}
class MainWindow : publicQMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
privateslots:
    void DisplayMsg(Msg);   //Msg!!!
private:
    Ui::MainWindow *ui;
    TestThread *t;
};
#endif //MAINWINDOW_H

mainwindow.cpp 文件

#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(newUi::MainWindow)
{
    ui->setupUi(this);
    //进行connect前必须实例化
    t = newTestThread();
    //Msg!!!
    connect(t, SIGNAL(TestSignal(Msg)), this, SLOT(DisplayMsg(Msg)));
    //执行子线程
    t->start();
}
voidMainWindow::DisplayMsg(Msg msg)
{
    ui->textBrowser->append(QString::number(msg.int_info));
    ui->textBrowser->append(msg.str_info);
}
MainWindow::~MainWindow()
{
    deleteui;
}

此时再进行编译,能够通过,但是Qt Creator会有提示

QObject::connect: Cannot queue arguments of type 'Msg'
(Make sure 'Msg' is registered using qRegisterMetaType().)

并且运行程序,不会有任何反应。需要对mainwindow类的构造方法进行改造。mainwindow.cpp文件改动(蓝色加粗部分)为:

//以上代码省略
ui->setupUi(this); qRegisterMetaType<Msg>("Msg");
//以下代码省略

此时能够正常运行。以上测试用例,经过本人亲测可用!!!!

[转]QT子线程与主线程的信号槽通信-亲测可用!第2张

结论:

(1)在线程间使用信号槽进行通信时,需要注意必须使用元数据类型,Qt内生的元数据类型,如int double QString 等。

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

参考链接:

1、QT子线程与主线程的信号槽通信-(重点参考)

2、Qt子线程如何更新UI,完整的代码示例,有图有真相-(重点参考)

3、QT其他线程和UI主线程通信方式

4、Qt5中运行后台网络读取线程与主UI线程互交

5、QT小例子GUI(主)线程与子线程之间的通信-子线程和主线程互相发送信号

6、QT线程发送消息通知界面小例

免责声明:文章转载自《[转]QT子线程与主线程的信号槽通信-亲测可用!》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇asp.net webapi 返回json结果的方法QUiLoader 动态加载.ui文件下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

node.js如何充分利用多核cpu?

Nodejs是基于chrome浏览器的V8引擎构建的,也就说明它的模型与浏览器是类似的。我们的JavaScript会运行在单个进程的单个线程上。 但是V8引擎的单进程单线程并不是完美的结构,现如今CPU基本上都是多核的。真正的服务器往往有好几个CPU(像我们的线上物理机有12个核),所以,这就将抛出Nodejs实际应用中的一个问题:“如何充分利用多核CPU...

为什么要用Volley中的RequestFuture封装RxJava来用异步请求处理同步请求?

前几天健哥喊我研究一下RvJava,在网络请求用,更简洁更有条理,然后就会抽空研究研究,现在项目里网络库是Volley,就结合项目和网上的demo看,突然脑袋蹦出这个问题,现在看起来这个问题有一点蠢蠢的。 firstly,名词解释一下。 Volley是谷歌爸爸给咱们封装好了的网络请求库,帮我们封装了具体的请求,线程切换以及数据转换,适合短小多并发的网络请求...

X窗口系统的协议和架构

转自X窗口系统的协议和架构 在电脑中,X窗口系统(常称作 X11、X)是一种以位图显示的网络透明化窗口系统。本条目详述 X11 的协议及其技术架构。 X C/S模型和网络透明性 X 基于C/S模型。运作在电脑上的X 服务器程序以图形显示,并以各种客户端程序进行通信。X 服务器接受图形输出(窗口画面)方面的请求,并回传使用者的输入(键盘、鼠标)。...

多线程死锁

多线程死锁:同步中嵌套同步,导致锁无法释放。 死锁解决办法:不要在同步中嵌套同步 public class Demo06DeadLock { public static void main(String[] args) { //创建线程任务对象 Ticket ticket = new Ticket();...

操作系统知识总结

操作系统 面向进程和线程学习操作系统。 目录 Chapter 1 Chapter 2 Chapter 3 Chapter 4 Chapter 5 进程线程模型 进程间通信 同步互斥机制 存储管理 网络I/O模型 内容 进程线程模型 线程和进程的概念已经在操作系统书中被翻来覆去讲了很多遍。很多概念虽然都是套话,但没能理解透其中深意会导致很多内容...

正确使用Android性能分析工具——TraceView

TraceView界面 现来看一下整个界面的图,整个界面包括上下两部分,上面是你测试的进程中每个线程的执行情况,每个线程占一行;下面是每个方法执行的各个指标的值 上面一部分是你测试进程的中每个线程运行的时间线,下图中可以可以看到,主要只有一个main线程在执行,因为我滑动了一下列表,main线程(UI线程)正在进行绘制View呢~~ 然后我点击了序号为13...