[转]QT子线程与主线程的信号槽通信-亲测可用!
近用QT做一个服务器,众所周知,QT的主线程必须保持畅通,才能刷新UI。所以,网络通信端采用新开线程的方式。在涉及到使用子线程更新Ui上的控件时遇到了点儿麻烦。网上提供了很多同一线程不同类间采用信号槽通信的方式,但是并不完全适合线程间的信号槽通信,这主要体现在自定义消息的传递上。
首先我们看看一般的方式:
利用信号-槽发送Qt内置的元数据类型
testthread.h 文件
#ifndef TESTTHREAD_H
#define TESTTHREAD_H #include <QThread> #include "msg.h" class TestThread : public QThread
{
Q_OBJECT
public:
explicit TestThread(QObject *parent = ); protected:
void run(); signals:
void TestSignal(int); private:
Msg msg;
}; #endif // TESTTHREAD_H
testthread.cpp文件
#include "testthread.h" TestThread::TestThread(QObject *parent) :
QThread(parent)
{
} void TestThread::run()
{
//触发信号
emit TestSignal();
}
自己定义的类继承了QThread类,重写run函数,然后触发TestSignal信号。
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H #include <QMainWindow> #include "testthread.h" namespace Ui {
class MainWindow;
} class MainWindow : public QMainWindow
{
Q_OBJECT public:
explicit MainWindow(QWidget *parent = );
~MainWindow(); private slots:
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(new Ui::MainWindow)
{
ui->setupUi(this); //进行connect前必须实例化
t = new TestThread(); connect(t, SIGNAL(TestSignal(int)), this, SLOT(DisplayMsg(int))); //执行子线程
t->start();
} void MainWindow::DisplayMsg(int a)
{
ui->textBrowser->append(QString::number(a));
} MainWindow::~MainWindow()
{
delete ui;
}
Mainwindow里面连接信号槽,并且将收到的int参数显示在界面上。
运行效果:
利用信号-槽发送自定义消息
下面我们对程序进行一些简单,修改,使得它传输我们的自定义消息。
testthread.h 文件
#ifndef TESTTHREAD_H
#define TESTTHREAD_H #include <QThread> #include "msg.h" class TestThread : public QThread
{
Q_OBJECT
public:
explicit TestThread(QObject *parent = );
Msg msg; protected:
void run(); signals:
void TestSignal(Msg); //Msg!!!
}; #endif // TESTTHREAD_H
testthread.h 文件
#include "testthread.h" TestThread::TestThread(QObject *parent) :
QThread(parent)
{
} void TestThread::run()
{
msg.int_info = ;
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" namespace Ui {
class MainWindow;
} class MainWindow : public QMainWindow
{
Q_OBJECT public:
explicit MainWindow(QWidget *parent = );
~MainWindow(); private slots:
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(new Ui::MainWindow)
{
ui->setupUi(this); //进行connect前必须实例化
t = new TestThread(); //Msg!!!
connect(t, SIGNAL(TestSignal(Msg)), this, SLOT(DisplayMsg(Msg))); //执行子线程
t->start();
} void MainWindow::DisplayMsg(Msg msg)
{
ui->textBrowser->append(QString::number(msg.int_info));
ui->textBrowser->append(msg.str_info);
} MainWindow::~MainWindow()
{
delete ui;
}
此时再进行编译,能够通过,但是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");
//以下代码省略
此时能够正常运行。以上测试用例,经过本人亲测可用!!!!
结论:
(1)在线程间使用信号槽进行通信时,需要注意必须使用元数据类型,Qt内生的元数据类型,如int double QString 等。
(2)如果要用自己定义的数据类型,需要在connect前将其注册为元数据类型。形式见代码。
参考链接:
1、QT子线程与主线程的信号槽通信-(重点参考)
2、Qt子线程如何更新UI,完整的代码示例,有图有真相-(重点参考)
5、QT小例子GUI(主)线程与子线程之间的通信-子线程和主线程互相发送信号
[转]QT子线程与主线程的信号槽通信-亲测可用!的更多相关文章
- Qt自己定义事件实现及子线程向主线程传送事件消息
近期在又一次学习Qt的时候,由于要涉及到子线程与主线程传递消息,所以便琢磨了一下.顺便把有用的记录下来,方便自己以后查询及各位同仁的參考! 特此声明,本篇博文主要讲述有用的,也就是直接说明怎么实现,就 ...
- WinForm 中使用 Action 子线程对主线程 控制进行访问
/// <summary> /// 开启新线程执行 /// </summary> /// <param name="sender"></p ...
- c# 子线程与主线程通信二
之前写过使用线程上下文实现线程同步,今天利用子线程向主线程发送事件,实现子线程与主线程的同步 基本步骤 1.定义类 using System; using System.Collections.Gen ...
- 19 Handler 子线程向主线程发送信息
案例一 Message创建三种方法: package com.example.day19_handler_demo1; import android.os.Bundle; import android ...
- C# 子线程与主线程通讯方法一
最近在项目中要用到子线程运行结束向主线程通知的需求,利用线程上下文来实现线程之间的同步. 子线程结束后调用同步函数,向主线程发送时间字符串,改变主窗体的label标签 label标签改变事件触发处理函 ...
- Android笔记(三十一)Android中线程之间的通信(三)子线程给主线程发送消息
先看简单示例:点击按钮,2s之后,TextView改变内容. package cn.lixyz.handlertest; import android.app.Activity; import and ...
- C# 子线程调用主线程窗体的解决方法
摘自其他人博客,自己试过确实解决问题.(如在自己定义的线程里面给textbox赋值) 由于Windows窗体控件本质上不是线程安全的.因此如果有两个或多个线程适度操作某一控件的状态(set value ...
- Android中,子线程使用主线程中的组件出现问题的解决方法
Android中,主线程中的组件,不能被子线程调用,否则就会出现异常. 这里所使用的方法就是利用Handler类中的Callback(),接受线程中的Message类发来的消息,然后把所要在线程中执行 ...
- Unity3d 创建线程 子线程与主线程通信
创建子线程 一,不带参数 Thread resourcesLoadThread=new Thread (this.resourceLoadTxt); resourcesLoadThread.Sta ...
随机推荐
- [PHP] 算法-快速排序的PHP实现
快速排序: 1.基于二分的思想 2.第一个作为基准数,左右各一个指针,同时扫描,右边先走,找到比基准数小的停下 左边再走,找到比基准数大的停下,左右交换 3.当左右相遇的时候,把当前的和基准数调换,递 ...
- oracle与mysql
『创业团队最佳选择是Oracle+MongoDB,而不是MySQL』,当深蓝在QQ群里抛出这样的观点的时候,就像是在马蜂窝里丢了一串鞭炮一样热闹起来. 创业者甲: 开什么玩笑,Oracle要收钱的,太 ...
- Java框架之Struts2(一)
在学习Struts2之前,我们要知道Java为什么要有反射机制呢?反射机制可以说是填补Java不能动态访问某一个类的空白.利用反射机制,动态的创建一个对象.动态的访问类的某个属性,而且访问哪一个属性自 ...
- 【Java基础】15、负数的二进制表示方法
在计算机中,负数以其正值的补码形式表达. 什么叫补码呢?这得从原码,反码说起. 原码:一个整数,按照绝对值大小转换成的二进制数,称为原码. 比如 00000000 00000000 00000000 ...
- CTO 之“六脉神剑”
他深谙电商之道,从零打造 1 号店网站及供应链系统,以技术引领业务发展.他是欧电云创始人韩军,下面将由他分享完美 CTO “六脉神剑”的经验之谈. 首先,从对 CTO 的一个认识误区讲起. 不写代码的 ...
- sublime3安装ctags追踪插件
sublime3经常要用到函数追踪插件,怎做的?下面看安装步骤: 1.安装package control 按快捷键 ctrl+shift+p 2.安装搜索 ctags插件 3.下载ctags可执行程序 ...
- 洛谷P4562 [JXOI2018]游戏(组合数学)
题意 题目链接 Sol 这个题就比较休闲了. \(t(p)\)显然等于最后一个没有约数的数的位置,那么我们可以去枚举一下. 设没有约数的数的个数有\(cnt\)个 因此总的方案为\(\sum_{i=c ...
- POJ 1113 Wall(思维 计算几何 数学)
题意 题目链接 给出平面上n个点的坐标.你需要建一个围墙,把所有的点围在里面,且围墙距所有点的距离不小于l.求围墙的最小长度. \(n \leqslant 10^5\) Sol 首先考虑如果没有l的限 ...
- TFS 安装遇到的问题
居然是是微信桌面客户端占用了8080端口,也是醉了... 1 VS链接 源码管理器 发现提示 Http 404, 发现原来是自己吧tfs 给删除了 2 重新安装tfs,过程中提示 8080 端口被占用 ...
- selenium 之百度搜索,结果列表翻页查询
selenium之百度搜索,结果列表翻页查询 by:授客 QQ:1033553122 实例:百度搜索,结果列表翻页查询 解决问题:解决selenium driver获取web页面元素时,元素过期问题 ...