当前位置: 首页 > news >正文

【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);}

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

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

相关文章:

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

往期回顾&#xff1a; 【QT入门】 lambda表达式(函数)详解-CSDN博客 【QT入门】 Qt槽函数五种常用写法介绍-CSDN博客 【QT入门】 Qt实现自定义信号-CSDN博客 【QT入门】 Qt自定义信号后跨线程发送信号 由于Qt的子线程是无法直接修改ui&#xff0c;需要发送信号到ui线程进行修改…...

51单片机学习笔记7 串转并操作方法

51单片机学习笔记7 串转并操作方法 一、串转并操作简介二、74HC595介绍1. **功能**&#xff1a;2. **引脚**&#xff1a;3. **工作原理**&#xff1a;4. 开发板原理图&#xff08;1&#xff09;8*8 LED点阵&#xff1a;&#xff08;2&#xff09;74HC595 串转并&#xff1a; 三…...

微服务cloud--抱团取暖吗 netflix很多停更了

抱团只会卷&#xff0c;卷卷也挺好的 DDD 高内聚 低耦合 服务间不要有业务交叉 通过接口调用 分解技术实现的复杂性&#xff0c;围绕业务概念构建领域模型&#xff1b;边界划分 业务中台&#xff1a; 数据中台&#xff1a; 技术中台&#xff1a; 核心组件 eureka&#x…...

牛客笔试|美团2024春招第一场【测试方向】

第一题&#xff1a;小美的数组询问 小美拿到了一个由正整数组成的数组&#xff0c;但其中有一些元素是未知的&#xff08;用 0 来表示&#xff09;。 现在小美想知道&#xff0c;如果那些未知的元素在区间 [l, r] 范围内随机取值的话&#xff0c;数组所有元素之和的最小值和最大…...

Docker搭建LNMP环境实战(一):前言

缘起&#xff1a;不久前学习了Docker相关知识&#xff0c;并在Docker环境下学习了LNMP环境的搭建。由于网上的文章大多没有翔实、可行的案例&#xff0c;很多文章都是断章取义&#xff0c;所以&#xff0c;期间踩了太多太多的坑&#xff0c;初学者想要真正顺利地搭建一套环境起…...

SCI一区 | Matlab实现PSO-TCN-BiGRU-Attention粒子群算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测

SCI一区 | Matlab实现PSO-TCN-BiGRU-Attention粒子群算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测 目录 SCI一区 | Matlab实现PSO-TCN-BiGRU-Attention粒子群算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测预测效果基本介绍模型描述…...

界面控件DevExpress ASP.NET Ribbon组件 - 完美复刻Office 365体验!

无论用户是喜欢传统工具栏菜单外观、样式&#xff0c;还是想在下一个项目中复制Office 365 web UI&#xff0c;DevExpress ASP.NET都提供了所需要的工具&#xff0c;帮助用户打造更好的应用程序界面。 P.S&#xff1a;DevExpress ASP.NET Web Forms Controls拥有针对Web表单&a…...

vue2【详解】mixins —— 抽离公共逻辑

mixins 用于在 Vue 中便捷复用变量、方法、组件引用、生命周期等 使用方法 创建文件myMixin.js export const myMixin {data() {return {webName: 朝阳的博客}},created() {alert(欢迎来到${this.webName})},methods: {hi() {alert(欢迎来到${this.webName})}} }vue文件中引入…...

ArrayList的常用方法

ArrayList是Java中常用的动态数组类&#xff0c;它提供了一系列用于操作和管理数组的方法。下面是一些ArrayList常用方法的介绍&#xff1a; add()方法&#xff1a;向ArrayList中添加元素&#xff0c;可以指定位置添加元素或者在末尾添加元素。 ArrayList<String> list …...

ES-Hadoop:将Elasticsearch与Hadoop无缝集成的开源工具

hadoop 大数据技术之Hive&#xff08;3&#xff09;PyHive pyhdfs ES,Elasticsearch https://zhuanlan.zhihu.com/p/595505475?utm_id0 Hadoop hdfs 、hive、spark https://blog.51cto.com/u_16099278/6901638 ES-Hadoop&#xff1a;将Elasticsearch与Hadoop无缝集成的开源工…...

质量模型、软件测试流程和测试用例

质量模型 衡量一个优秀软件的维度 可以从功能性、性能、兼容性、易用性、安全、可靠性、可维护性、可移植性这几个方面去做软件测试&#xff0c;但咱们在正常测试中一般是选取前五项进行测试 测试流程 1、需求评审&#xff1a;确保各部门对需求的理解一致 2、测试计划编写&a…...

集简云新增“文本语音转换”功能,实现智能语音交互

为丰富人工智能领域的应用集成&#xff0c;为用户提供更便捷和智能化的信息获取和视觉创作方式&#xff0c;本周集简云上线了内置应用—文本语音转换。目前支持OpenAI TTS和TTS HD模型&#xff0c;实现文本语音高效智能转换&#xff0c;也可根据你的产品或品牌创建独特的神经网…...

图像处理领域专业术语

图像处理中的一些常见术语&#xff0c;涵盖了从基础概念到高级处理技术的各个方面。 以下是一些图像处理领域常用的专业术语及其解释&#xff1a; 像素&#xff08;Pixel&#xff09;&#xff1a; 图像的最基本单元&#xff0c;每个像素都有一个或多个与其关联的数值&#xff0…...

Microsoft Edge 中的 Internet Explorer 模式解决ie禁止跳转到edge问题

作为网工&#xff0c;网络中存在很老的设备只能用ie浏览器访问打开&#xff0c;但是win10后打开Internet Explorer 会强制跳转到Edge 浏览器&#xff0c;且有人反馈不会关&#xff0c;为此找到了微软官方的Microsoft Edge 中的 Internet Explorer 模式&#xff0c;可以直接在Mi…...

理清大数据技术与架构

大数据并不是一个系统软件&#xff0c;更不是一个单一的软件&#xff0c;它实际上是一种技术体系、一种数据处理方法&#xff0c;甚至可以说是一个服务平台。在这个技术体系中&#xff0c;涵盖了许多不同的部件&#xff0c;比如Hadoop服务平台。这一服务平台可以根据具体情况自…...

小白DB补全计划Day2-LeetCode:SQL基本操作selectJOIN

链接&#xff1a;1683. 无效的推文 - 力扣&#xff08;LeetCode&#xff09;1378. 使用唯一标识码替换员工ID - 力扣&#xff08;LeetCode&#xff09;1068. 产品销售分析 I - 力扣&#xff08;LeetCode&#xff09; 来源&#xff1a;LeetCode 1683 # Write your MySQL quer…...

【Node.js从基础到高级运用】十五、单元测试与集成测试

引言 在Node.js开发过程中&#xff0c;测试是确保代码质量和功能正确性的关键步骤。单元测试和集成测试是最常见的测试类型。下面我们将使用Jest框架来进行测试。 单元测试 单元测试是指对软件中的最小可测试单元进行检查和验证。在Node.js中&#xff0c;这通常指的是函数或者…...

哈工大sse C语言 困难

Q565.(10分数, 语言: C)程序中函数 fun()的功能: 将一个由八进制数字字符组成的字符串转换为与其值相等的十进制整数。规定输入的字符串最多只能包含5位八进制数字字符。 **输入格式要求&#xff1a;gets 提示信息&#xff1a;"输入一个八进制字符串&#xff08;5位&…...

力扣● 503.下一个更大元素II ● 42. 接雨水

503.下一个更大元素II 与496.下一个更大元素 I的不同是要循环地搜索元素的下一个更大的数。那么主要是对于遍历结束后&#xff0c;单调栈里面剩下的那些元素。 如果直接把两个数组拼接在一起&#xff0c;然后使用单调栈求下一个最大值就可以。 代码实现的话&#xff0c;不用直…...

Java中的包装类

Java中的包装类 一、包装类是什么&#xff1f;二、对应关系&#xff1a;三、举例说明&#xff1a;Integer构造器&#xff1a;包装类特有的机制&#xff1a;自动装箱 自动拆箱常用方法 总结 一、包装类是什么&#xff1f; 以前定义变量&#xff0c;经常使用基本数据类型&#x…...

搭建DNS域名解析服务器(正向解析资源文件)

正向解析资源文件 1&#xff09;准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2&#xff09;服务端安装软件&#xff1a;bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent

安全大模型训练计划&#xff1a;基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标&#xff1a;为安全大模型创建高质量、去偏、符合伦理的训练数据集&#xff0c;涵盖安全相关任务&#xff08;如有害内容检测、隐私保护、道德推理等&#xff09;。 1.1 数据收集 描…...

【版本控制】GitHub Desktop 入门教程与开源协作全流程解析

目录 0 引言1 GitHub Desktop 入门教程1.1 安装与基础配置1.2 核心功能使用指南仓库管理日常开发流程分支管理 2 GitHub 开源协作流程详解2.1 Fork & Pull Request 模型2.2 完整协作流程步骤步骤 1: Fork&#xff08;创建个人副本&#xff09;步骤 2: Clone&#xff08;克隆…...

二叉树-226.翻转链表-力扣(LeetCode)

一、题目解析 翻转可以理解为树的左右子树交换&#xff0c;从根到叶子节点&#xff0c;但是这里交换的是链接的指针&#xff0c;而不是单纯的交换值&#xff0c;当出现nullptr时&#xff0c;也是可以交换链接的&#xff0c;交换值的话就不行了。 二、算法原理 依旧的递归&…...

【从零学习JVM|第二篇】字节码文件

前言&#xff1a; 通过了解字节码文件可以帮助我们更容易的理解JVM的工作原理&#xff0c;所以接下来&#xff0c;我们来介绍一下字节码文件。 目录 前言&#xff1a; 正确的打开字节码文件 字节码文件组成 1. 魔数&#xff08;Magic Number&#xff09; 2. 版本号&…...

leetcode_66.加一

题目链接 这道题归类在力扣的数学类中&#xff0c;应该算是一道思维的简单题吧 题是这样的&#xff0c;根据题目我们不难理解&#xff0c;这个题就是在最后一位加 1 然后返回&#xff0c;正如示例所说的那样&#xff0c;当然这很符合我们人的思维&#xff0c;写这种算法题最重要…...

用电脑通过USB总线连接控制keysight示波器

通过USB总线控制示波器的优势 在上篇文章我介绍了如何通过网线远程连接keysight示波器&#xff0c;如果连接的距离不是很远&#xff0c;也可以通过USB线将示波器与电脑连接起来&#xff0c;实现对示波器的控制和截图。 在KEYSIGHT示波器DSOX1204A的后端&#xff0c;除了有网口…...

深入理解React Hooks的原理与实践

深入理解React Hooks的原理与实践 引言 React Hooks 自 2018 年 React 16.8 发布以来&#xff0c;彻底改变了前端开发者的编码方式。它通过函数式组件提供了状态管理和生命周期等功能&#xff0c;取代了传统的类组件&#xff0c;使得代码更加简洁、复用性更强。然而&#xff…...

Asp.Net Core基于StackExchange Redis 缓存

NuGet安装 StackExchange.Redis Microsoft.Extensions.Options 0. appsettings.json初始化配置 {"Logging": {"LogLevel": {"Default": "Information","Microsoft.AspNetCore": "Warning"}},"AllowedHos…...