【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.mzph.cn/news/763377.shtml

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

相关文章

【Unity投屏总结】投屏方案总结

【背景】 想方便自己在VR中工作&#xff0c;打算做一个能够挂多个屏幕的远程控制VR桌面。研究下来发现细分场景有很多&#xff0c;有点鱼和熊掌不可兼得的意味&#xff0c;细分如下。 【投屏场景与解决方案】 希望多人能够同时观看我的屏幕&#xff0c;也就是一屏投多屏&…

C语言知识复盘— 递归算法 | 函数 | 数组

递归 ○ 算法思想&#xff1a; 递归算法分为两大阶段 : 递和归&#xff0c;即就是有去&#xff08;递去&#xff09;有回&#xff08;归来&#xff09;。 递去&#xff1a;将递归问题分解为若干个规模较小,与原问题形式相同的子问题,这些子问题可以用相同的解题思路来解决。归…

spring cloud项目微服务间互相调用使用自定义标注进行鉴权方案

来吧&#xff0c;贴代码。 一、背景 我们有一个项目使用了spring cloud&#xff0c;有的微服务需要调用别的微服务&#xff0c;但这些调用没有鉴权&#xff1b;当初项目时间非常紧&#xff0c;同时这部分微服务有的对外也没有鉴权&#xff0c;在代码中设置了无须鉴权&#xf…

字节跳动面试被拷打:高效处理大量数据的JavaScript技巧

一、文章内容 时间分片宏任务微任务前置内容实现时间分片 二、时间切片 什么是时间切片&#xff1f;通过字面意思我们不难理解时间切片就是将时间分成多个片段进行一一渲染数据,时间切片是个抽象的问题,我们可能会想到JavaScript中window自带的setTimeout的延迟函数或者是 w…

Docker进阶教程 - 2 Docker部署SpringBoot项目

更好的阅读体验&#xff1a;点这里 &#xff08; www.doubibiji.com &#xff09; 2 Docker部署SpringBoot项目 已经学习了 Dockerfile 了&#xff0c;下面介绍一下如何将 SpringBoot 项目通过 Dockerfile 来部署到 Docker 中。 1 修改项目配置 首先需要准备一个 SpringBo…

初识二叉树

文章目录 一.什么是树二.什么是二叉树三.二叉树的访问次序四.特殊的二叉树五.求结点个数六.平衡二叉树总结 一.什么是树 树是由一个集合以及在该集合上定义的一种关系构成的。 集合中的元素称为树的节点&#xff0c;所定义的关系称为父子关系。 父子关系在树的节点之间建立了一…

安装OneNote for Win10 | Win10/Win11

前言 PC端的OneNote分为2个版本&#xff0c;分别是Microsoft Store版本和Office版本&#xff0c;Microsoft Store版本即为OneNote for Win10&#xff0c;此版的OneNote有最近笔记功能&#xff0c;但检索功能不如Office版本&#xff0c;个人认为2个版本各有优劣。 但OneNote f…

新人应该从哪几个方面掌握大数据测试?

什么是大数据 大数据是指无法在一定时间范围内用传统的计算机技术进行处理的海量数据集。 对于大数据的测试则需要不同的工具、技术、框架来进行处理。 大数据的体量大、多样化和高速处理所涉及的数据生成、存储、检索和分析使得大数据工程师需要掌握极其高的技术功底。 需要你…

nodejs中使用@maxmind/geoip2-node 查询地理位置信息

介绍 maxmind/geoip2-node 是一个Node.js模块&#xff0c;用于与MaxMind的GeoIP2数据库进行交互&#xff0c;从而获取IP地址的地理位置信息。MaxMind的GeoIP2数据库包含了全球范围内的IP地址和对应的地理位置信息&#xff0c;如国家、城市、经纬度等。使用maxmind/geoip2-node…

Python连接MariaDB数据库

2024软件测试面试刷题&#xff0c;这个小程序&#xff08;永久刷题&#xff09;&#xff0c;靠它快速找到工作了&#xff01;&#xff08;刷题APP的天花板&#xff09;【持续更新最新版】-CSDN博客 Python连接MariaDB数据库 一、安装mariadb库 pip install mariadb 二、连接…

机器视觉学习(六)—— 图像的颜色识别

目录 一、色彩空间 1.1 RGB色彩空间 1.2 HSV色彩空间 1.3 灰度 1.4 CMYK色彩空间 1.5 Lab色彩空间 二、色彩空间转换 三、识别颜色 3.1 识别一种特定的颜色 3.2 识别多种颜色 一、色彩空间 计算机视觉中常用的色彩空间有RGB色彩空间、HSV色彩空间、CMYK色彩空间、La…

34-Java传输对象模式 ( Transfer Object Pattern )

Java传输对象模式 实现范例 传输对象模式&#xff08;Transfer Object Pattern&#xff09;用于从客户端向服务器一次性传递带有多个属性的数据传输对象也被称为数值对象&#xff0c;没有任何行为传输对象是一个具有 getter/setter 方法的简单的 POJO 类&#xff0c;它是可序列…

解锁AI之门:协助探索Amazon Bedrock服务

AI愈加强大的功能和广泛的应用场景&#xff0c;正逐渐改变着我们的工作和生活方式。 Amazon Bedrock在AI的时代潮流中&#xff0c;也以其强大而灵活的功能特性&#xff0c;正在成为越来越多企业和个人的智能助手。 亚马逊云科技通过VERYCLOUD睿鸿股份的服务能力&#xff0c;使…

揭秘!自定义三维模型如何在RflySim中实现仿真(一)

一.技术背景 在无人系统研发过程中&#xff0c;需要进行大量的运动控制系统半物理实时仿真实验&#xff0c;传统仿真界面的运动轨迹显示多采用的是二维曲线形式&#xff0c;运动过程和状态是通过文本数据显示。随着数据量的增加&#xff0c;该方式缺乏直观性&#xff0c;不易观…

python四川火锅文化网站的设计与实现flask-django-php-nodejs

四川火锅文化网站的目的是让使用者可以更方便的将人、设备和场景更立体的连接在一起。能让用户以更科幻的方式使用产品&#xff0c;体验高科技时代带给人们的方便&#xff0c;同时也能让用户体会到与以往常规产品不同的体验风格。 与安卓&#xff0c;iOS相比较起来&#xff0c;…

蓝桥杯单片机快速开发笔记——特训2 按键的长按与短按

一、题目要求 在CT107D单片机综合训练平台上&#xff0c;通过I/O模式编写代码&#xff0c;实现以下功能&#xff1a; 系统上电后&#xff0c;关闭蜂鸣器、继电器和全部指示灯&#xff0c;数码管显示初始值为28&#xff0c;仅显示数码管最右边两位。利用定时器0实现10ms间隔定…

预测一下,GPT-5 会在什么时候发布,又会有哪些更新?

发布预期&#xff1a;GPT-5预计将于11月发布&#xff0c;可能与ChatGPT发布两周年同期。竞争态势&#xff1a;谷歌的Gemini与GPT-4 turbo已展开竞争。逐步发布&#xff1a;GPT-5可能通过模型训练过程中的中间检查点逐步发布。训练与安全测试&#xff1a;实际训练可能需3个月&am…

发布 AUR 软件包 (ArchLinux)

首发日期 2024-03-09, 以下为原文内容: 理论上来说, 我们应该平等的对待每一个 GNU/Linux 发行版本. 但是, 因为窝日常使用 ArchLinux, 所以对 ArchLinux 有一些特别的优待, 比如自己做的软件优先为 ArchLinux 打包发布. 本文以软件包 librush-bin 为例, 介绍发布 AUR 软件包的…

【IC设计】Verilog线性序列机点灯案例(四)(小梅哥课程)

文章目录 该系列目录&#xff1a;设计环境设计目标设计思路RTL及Testbench代码RTL代码Testbenchxdc约束 仿真结果 声明&#xff1a;案例和代码来自小梅哥课程&#xff0c;本人仅对知识点做做笔记&#xff0c;如有学习需要请支持官方正版。 该系列目录&#xff1a; Verilog线性…

力扣热门算法题 52. N 皇后 II,53. 最大子数组和,54. 螺旋矩阵

52. N 皇后 II&#xff0c;53. 最大子数组和&#xff0c;54. 螺旋矩阵&#xff0c;每题做详细思路梳理&#xff0c;配套Python&Java双语代码&#xff0c; 2024.03.20 可通过leetcode所有测试用例。 目录 52. N 皇后 II 解题思路 完整代码 Python Java 53. 最大子数组…