【QT入门】 Qt自定义信号后跨线程发送信号

往期回顾:

【QT入门】 lambda表达式(函数)详解-CSDN博客

【QT入门】 Qt槽函数五种常用写法介绍-CSDN博客

【QT入门】 Qt实现自定义信号-CSDN博客

 【QT入门】 Qt自定义信号后跨线程发送信号

由于Qt的子线程是无法直接修改ui,需要发送信号到ui线程进行修改,所以会跨线程发送信号。

一、思路

思路基本一致,子线程发送一个信号,父线程接收信号并执行槽函数,把子线程传递的数据展示在父线程ui上。

二、步骤

1.如何创建子线程

右键单击项目,选择Add New->C++>C++ Class即可

ChildThread是我们自己取的子线程名字
下面的基类因为没有合适的基类,我们选择Custom,继承QThread类

这里注意,创建以后由于是自己填的继承自QThread类,它不一定包含了相应的头文件,需要我们自己补上。

2、添加Q_OBJECT宏

自己创建的子线程是不包含Q_OBJECT宏的,如果需要用到信号槽,需要自己补上Q_OBJECT ,一般建议大家不管用不用,创建后就都补上。

3、子线程重写run方法

子线程继承父线程之后需要重写父线程的run方法,关于线程这一块知识点,后续会有更加详细的讲解,比如:子线程重写的run方法在子线程里,但是其构造函数却是在父线程里等

void ChildThread::run()
{//打印当前线程的线程号qDebug()<<"child thread id= "<<QThread::currentThreadId();Score s;s.name="zhangsan";s.age=18;s.id=001;emit sig_sendScore(s);}

注:

当我们分不清代码运行在哪个线程的时候,可以用QThread::currentThreadId();方法打印当前线程的线程号来判断。

这里数据方面用了一个结构体来写数据

struct Score
{string name;int age;int id;
};

4、启动子线程

 父线程按钮点击的槽函数里创建子线程,接受子线程的信号并启动子线程

void Widget::on_btnOpen_clicked()
{ChildThread *ch =new ChildThread();connect(ch,&ChildThread::sig_sendScore,[=](Score s){string info="name="+s.name+" age="+to_string(s.age)+" id="+to_string(s.id);ui->lineEdit->setText(QString::fromStdString(info));});qDebug()<<"widget thread id= "<<QThread::currentThreadId();ch->start();
}

针对代码看几个注意点:

1、要在Qt用c++的string类型,一个加头文件,二个加命名空间
2、age和id这种int类型要转成string,用一个to_string(),复习,int转Qstring?用QString::number()
3、setText放的是QString类型的,这里info是string类型,所以需要转QString,用QString::fromStdString()

但是,由于ChildThread的ch对象的槽函数sig_sendScore连接到了lambda表达式中,lambda表达式可能在ChildThread的线程中执行。这导致槽函数执行时在ChildThread的线程中运行,而不是在主线程中。

为了让槽函数在父线程执行,要么不用lambda表达式,改用槽函数,要么改写lambda表达式

4.1 改用槽函数
void Widget::on_btnOpen_clicked()
{ChildThread *ch =new ChildThread();connect(ch,&ChildThread::sig_sendScore,this,&Widget::showIofo);qDebug()<<"ui01 thread id= "<<QThread::currentThreadId();ch->start();
}
4.2 改写lambda表达式
void Widget::on_btnOpen_clicked()
{ChildThread *ch =new ChildThread();connect(ch, &ChildThread::sig_sendScore, this, [=](Score s){string info = "name=" + s.name + " age=" + to_string(s.age) + " id=" + to_string(s.id);ui->lineEdit->setText(QString::fromStdString(info));qDebug()<<"slots thread id= "<<QThread::currentThreadId();}, Qt::QueuedConnection);qDebug()<<"ui01 thread id= "<<QThread::currentThreadId();ch->start();
}

使用Qt::QueuedConnection连接信号和槽,这样信号会被投递到接收者所在的线程中执行。可以确保槽函数在接收者所在的线程中执行,从而解决可能的线程问题。

三、报错

当成功在父线程执行后,报了一个错误:

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

这是告诉我们Score是一个非基础类型参数,需要进行注册,在子线程的构造函数实现里注册即可

ChildThread::ChildThread()
{//非基础类型参数注册qRegisterMetaType<Score>("Score");
}

四、最终代码

 最后,附上最终代码,以便供大家参考

1、widget.h

#ifndef WIDGET_H
#define WIDGET_H
#include "childthread.h"
#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private slots:void on_btnOpen_clicked();void showIofo(Score s);private:Ui::Widget *ui;
};
#endif // WIDGET_H

2、widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);
}Widget::~Widget()
{delete ui;
}void Widget::on_btnOpen_clicked()
{ChildThread *ch =new ChildThread();//ch对象的槽函数sig_sendScore连接到了lambda表达式中,lambda表达式可能在ChildThread的线程中执行。//这可能导致槽函数执行时在ChildThread的线程中运行,而不是在主线程中。
//    connect(ch,&ChildThread::sig_sendScore,[=](Score s){
//        string info="name="+s.name+" age="+to_string(s.age)+" id="+to_string(s.id);
//        ui->lineEdit->setText(QString::fromStdString(info));
//        qDebug()<<"slots thread id= "<<QThread::currentThreadId();
//    });//    connect(ch, &ChildThread::sig_sendScore, this, [=](Score s){
//        string info = "name=" + s.name + " age=" + to_string(s.age) + " id=" + to_string(s.id);
//        ui->lineEdit->setText(QString::fromStdString(info));
//        qDebug()<<"slots thread id= "<<QThread::currentThreadId();
//    }, Qt::QueuedConnection);//connect(ch,&ChildThread::sig_sendScore,this,&Widget::showIofo);qDebug()<<"ui01 thread id= "<<QThread::currentThreadId();ch->start();
}void Widget::showIofo(Score s)
{qDebug()<<"ui02 thread id= "<<QThread::currentThreadId();string info="name="+s.name+" age="+to_string(s.age)+" id="+to_string(s.id);//setText放的是QString类型的,这里info是string类型,所以需要转QStringui->lineEdit->setText(QString::fromStdString(info));
}

3、childthread.h

#ifndef CHILDTHREAD_H
#define CHILDTHREAD_H
#include <QThread>
#include <string>using namespace std;//定义一个结构体函数
struct Score
{string name;int age;int id;
};class ChildThread : public QThread
{Q_OBJECTpublic:ChildThread();protected:void run() override ;signals:void sig_sendScore(Score s);};#endif // CHILDTHREAD_H

4、childthread.cpp

#include "childthread.h"
#include <QDebug>
ChildThread::ChildThread()
{//非基础类型参数注册qRegisterMetaType<Score>("Score");
}void ChildThread::run()
{//打印当前线程的线程号qDebug()<<"child thread id= "<<QThread::currentThreadId();Score s;s.name="zhangsan";s.age=18;s.id=001;emit sig_sendScore(s);}

都看到这里了,点个赞再走呗朋友~

加油吧,预祝大家变得更强!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/289684.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Swagger3探索之游龙入海

引言 后端开发中常用的接口调用工具一般使用Postman、ApiPost工具&#xff0c;但后期需要与前端联调&#xff0c;要补充接口文档花费大量时间&#xff0c;此时Swagger3应运而生&#xff0c;大大提高沟通交流的效率。 引用依赖 <!-- Swagger3 调用方式 http://ip:port/swa…

【容器源码篇】Set容器(HashSet,LinkedHashSet,TreeSet的特点)

文章目录 ⭐容器继承关系&#x1f339;Set容器&#x1f5d2;️HashSet源码解析构造方法public HashSet()public HashSet(Collection<? extends E> c)public HashSet(int initialCapacity, float loadFactor)HashSet(int initialCapacity, float loadFactor, boolean dum…

Mysql数据库:高级SQL语言详解

目录 前言 一、按关键字排序查询 1、单字段排序 1.1 按某一字段升序排序 1.2 按某一字段降序排序 1.3 结合where进行条件进行排序 2、多字段排序 2.1 按多字段升序排序 2.2 按多字段降序排序 2.3 案例操作 3、区间判断及查询不重复记录 3.1 区间判断 3.1.1 AND/OR…

iOS - Runtime-API

文章目录 iOS - Runtime-API1. Runtime应用1.1 字典转模型1.2 替换方法实现1.3 利用关联对象给分类添加属性1.4 利用消息转发机制&#xff0c;解决方法找不到的异常问题 2. Runtime-API2.1 Runtime API01 – 类2.1.1 动态创建一个类&#xff08;参数&#xff1a;父类&#xff0…

Linux课程____Samba文件共享服务

一、 Samba服务基础 SMB协议&#xff0c;服务消息块 CIFS协议&#xff0c;通用互联网文件系统 1.Samba 服务器的主要程序 smbd:提供对服务器中文件、打印资源的共享访问 nmbd:提供基于 NetBlOS 主机名称的解析 2.目录文件 /etc/samba/smb.conf 检查工具&#xff1a;test…

开源 | 电动汽车充换电解决方案,从智能硬件到软件系统,全部自主研发

文章目录 一、产品功能部分截图1.手机端&#xff08;小程序、安卓、ios&#xff09;2.PC端 二、小程序体验账号以及PC后台体验账号1.小程序体验账号2.PC后台体验账号关注公众号获取最新资讯 三、产品简介&#xff1f;1. 充电桩云平台&#xff08;含硬件充电桩&#xff09;&…

【全套源码教程】基于SpringBoot+MyBatis+Vue的电商智慧仓储管理系统的设计与实现

前言 博主简介&#x1f468;&#x1f3fc;‍⚕️&#xff1a;国内某一线互联网公司全栈工程师&#x1f468;&#x1f3fc;‍&#x1f4bb;&#xff0c;业余自媒体创作者&#x1f4bb;&#xff0c;CSDN博客专家&#x1f3c6;&#xff0c;Java领域优质创作者&#x1f4d5;&#x…

Java实现猜数字游戏:编程入门之旅

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

新能源汽车充电桩站点烟火AI识别检测算法应用方案

新能源汽车作为现代科技与环保理念的完美结合&#xff0c;其普及和应用本应带给人们更加便捷和绿色的出行体验。然而&#xff0c;近年来新能源汽车充电火灾事故的频发&#xff0c;无疑给这一领域投下了巨大的阴影。这不禁让人深思&#xff0c;为何这一先进的交通工具在充电过程…

【Leetcode】单链表常见题

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;Leetcode刷题 本节内容我们来讲解常见的几道单链表的题型&#xff0c;文末会赋上单链表增删查&#xff0c;初始化等代码 目录 1.移除链表元素2.链表的中间节点3.返回倒数第K个节点&#xff1a;4.环…

It takes two (搜索)

本题链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 题目&#xff1a; 样例&#xff1a; 输入 3 4 AAAO AAAA AAAA 输出 NO 思路&#xff1a; 根据题目意思&#xff0c;如果存在的 A 联通不可以成为 矩形&#xff0c;输出 NO&#xff0c;否则输出 YES 这道题看数据范…

windwos权限维持

1.php 不死马权限维持 <?php ignore_user_abort(); //关掉浏览器&#xff0c;PHP脚本也可以继续执行. set_time_limit(0);//通过set_time_limit(0)可以让程序无限制的执行下去 $interval 5; // 每隔*秒运行 do { $filename test.php; if(file_exists($filename)) { echo…

你是工作了十年,还是工作一年,重复了十遍?

你是工作了十年&#xff0c;还是工作一年&#xff0c;重复了十遍&#xff1f; 很多人刻舟求剑、画地为牢&#xff0c;就是缺少复盘意识。 没有复盘&#xff0c;没有进步。这是来自 B 站 Up 主檀东东Tango的复盘四步法&#xff1a; &#x1f449; https://www.bilibili.com/v…

Leaflet 中创建一个二维地图

要在 Leaflet 中创建一个二维地图&#xff0c;需要以下步骤&#xff1a; 1. 引入 Leaflet 库 首先&#xff0c;你需要在 HTML 文件中引入 Leaflet 库的 CSS 和 JavaScript 文件。你可以从官方网站下载 Leaflet&#xff0c;或者通过 CDN 引入。 <!-- Leaflet CSS --> &…

uni-app中web-view的使用

1. uni-app中web-view的使用 uni-app中的web-view是一个 web 浏览器组件&#xff0c;可以用来承载网页的容器&#xff0c;uni-app开发的app与web-view实现交互的方式相关简单&#xff0c;应用通过属性message绑定触发事件&#xff0c;然后在web-view的网页向应用 postMessage 触…

高防服务器、高防IP、高防CDN的工作原理是什么

高防IP高防CDN我们先科普一下是什么是高防。“高防”&#xff0c;顾名思义&#xff0c;就犹如网络上加了类似像盾牌一样很高的防御&#xff0c;主要是指IDC领域的IDC机房或者线路有防御DDOS能力。 高防服务器主要是比普通服务器多了防御服务&#xff0c;一般都是在机房出口架设…

智能算法-遗传算法 学习笔记

适应度的计算可类别为神经网络的目标函数&#xff0c;但此算法属于无监督学习&#xff0c;宏观来讲为搜寻最优解&#xff08;梯度&#xff09;的方式不同&#xff1f; 但神经网络中好像并不存在变异操作&#xff08;参数矩阵突变&#xff09;&#xff1f; 交叉的话残差网络ResN…

文件夹无法压缩是怎么回事?很简单的一个小原因~

电脑为什么显示没法压缩了&#xff0c;明明后台没有打开文件&#xff0c;却提示另一个程序正在使用文件&#xff0c;无法访问&#xff0c;压缩失败。 通常这种情况是因为后台有程序正在读取你准备压缩的文件&#xff0c;例如使用wps和office修改了word、excel、ppt等文件还未保…

OpenHarmony实战开发-Web组件的使用

介绍 本篇Codelab使用ArkTS语言实现一个简单的免登录过程&#xff0c;向大家介绍基本的cookie管理操作。主要包含以下功能&#xff1a; 获取指定url对应的cookie的值。设置cookie。清除所有cookie。免登录访问账户中心。 原理说明 本应用旨在说明Web组件中cookie的管理操作。…

第十四届蓝桥杯JavaA组省赛真题 - 互质数的个数

解题思路&#xff1a; 快速幂 欧拉函数 快速幂比较常见于数据较大的取模场景&#xff0c;欧拉函数感觉还是有点抽象 注意&#xff1a; 取模的时候就不要简写了&#xff0c;例如&#xff1a;res res * a % mod;不要写成res * a % mod; import java.util.Scanner;public c…