QT学习_14_一种开线程来实现串口通信方法

news2024/11/28 19:50:03

基于QT的上位机软件,和下位机一般都存在通信。 但如果是在主窗体类里面实现通信,往往会和主线程争抢CPU,导致通信非常容易出现异常。 最好的方式是给通信程序单独开一个线程来实现,而主窗体类(主线程)则主要专注于用户的交互逻辑。本文将以串口通信为例,来讲解一下如何单独为串口通信开一个线程。

正文

QT直接与多线程相关的内容是比较多的,说实话本人也没怎么看,也不是本文重点,本文介绍的开线程的方式,可能是有点讨巧的方式,但这种方式用起来还是很稳定的,之所以学到这种方式,估计也是因为这种方式广大网友用的多,比较流行。

QObject类有一个函数是 moveToThread,帮助文档的介绍如下

这个函数它主要的作用的就是改变本对象及其子对象的线程相关性。 但它要求了调用这函数的对象是不能有父对象,如果有父对象那就无法改变线程相关性。

据我了解,好像Qt里面的绝大部分类(还是所有的类)都是继承自QObject的,所以呢,串口通信类QSerialPort肯定也是继承自QObject的,那么它同样呢,也是可以调用moveToThread这个函数的。那本文提到的开线程方式呢,就是自己创建一个类“ESerialPort”,然后继承自QSerialPort。然后调用moveToThread函数,把它自己移动到线程当中去。好的,下面给出具体的参考代码如下:

首先我们来看自己定义的ESerialPort的.h文件

#ifndef ESERIALPORT_H
#define ESERIALPORT_H

#include <QtCore/QObject>
#include <QSerialPort>

class ESerialPort : public QSerialPort
{
    Q_OBJECT
public:
    ESerialPort(QObject *parent = nullptr);

signals:


public slots:


private:


};
#endif // ESERIALPORT_H

 然后是 .cpp文件

#include "eserialport.h"

ESerialPort::ESerialPort(QObject *parent) : QSerialPort(parent)
{

}

 这个类可以具有QSerialPort的所有功能,同时还能扩充一些自定义的功能。

好,那么我们来看看,具体怎么把这个类弄到线程中去,请看下面的参考代码。

我们的主窗体类的名字叫fugu哈,我自己取的,含义不用深究

.h文件

#ifndef FUGU_H
#define FUGU_H

#include <QMainWindow>
#include "eserialport.h"
#include <QThread>

namespace Ui {
class fugu;
}

class fugu : public QMainWindow
{
    Q_OBJECT

public:
    explicit fugu(QWidget *parent = nullptr);
    ~fugu();

signals:

private slots:

private:
    Ui::fugu *ui;

    ESerialPort *m_pserial_port;
    QThread * m_pthread_serial_port;

 

};

#endif // FUGU_H

注意看,在主窗体类里面,我们在private里面定义了两个私有变量,等会将会在初始化函数中用到。

    ESerialPort *m_pserial_port;
    QThread * m_pthread_serial_port;

.cpp文件

#include "fugu.h"
#include "ui_fugu.h"
#include <stack>
#include <stack.h>

fugu::fugu(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::fugu)
{
    ui->setupUi(this);


    // 串口通信单独开一个线程
    m_pserial_port = new ESerialPort;
    m_pthread_serial_port = new QThread(this);
    m_pserial_port->moveToThread(m_pthread_serial_port);
    m_pthread_serial_port->start();
    connect(this, &QObject::destroyed,[=](){
        m_pthread_serial_port->exit();
        m_pthread_serial_port->wait();
        delete m_pserial_port;
    });

}

fugu::~fugu()
{
    delete ui;
}

第一点要注意的是这行代码

m_pserial_port = new ESerialPort;

它有没有指定父对象, 是不是没有?  前面我们提到了,它是不能指定父对象的,如果指定父对象了,那就无法实现moveToThread的功能。

继续往下看

m_pthread_serial_port = new QThread(this);

但是咱们的线程对象是可以指定父对象的,为什么呢?  A QThread object manages one thread of control within the program. 它本身就是用来管理线程的。感觉指定父对象可以这样去理解,就是fugu是主线程,m_pthread_serial_port是fugu的子线程。 它后面还专门提到了用QObject::moveToThread()这个函数把worker objects移动进来。那么本例的worker objects是什么呢?就是自定义类ESerialPort的对象m_pserial_port。

所以,就有了第三行

m_pserial_port->moveToThread(m_pthread_serial_port);

第四行是开启这个线程没什么好说的

m_pthread_serial_port->start();

最后这个connect也是需要关注的,目的就是在主窗体类关闭的时候,给这个线程释放资源,以前我总是忽略这点,关闭程序的时候总是提示异常。就是因为没有加这一行。 大家也不必纠结,直接照抄就行了(未来的我也会直接照抄🙂)。

    connect(this, &QObject::destroyed,[=](){
        m_pthread_serial_port->exit();
        m_pthread_serial_port->wait();
        delete m_pserial_port;
    });

不知道大家注意到没有,无论是主窗口类还是自定义串口类,它们的.h文件中,都有

signals:
public slots:

熟悉它们的朋友肯定知道信号函数与槽函数的声明就得放在它们下面。具体的内容将在另一篇QT学习_15_线程间通信以及注意事项-CSDN博客继续讲解,欢迎阅读。

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

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

相关文章

全自动内衣洗衣机什么牌子好?好用又便宜的内衣洗衣机测评

在内衣洗衣机越来越受欢迎的今天&#xff0c;不少朋友都在犹豫要不要买一台内衣洗衣机&#xff0c;专门来清洗一些自身的贴身衣物&#xff0c;这个问题的答案是很有必要的&#xff0c;因为目前市场上的大型洗衣机只是起到了清洁的作用&#xff0c;并不能有效地清洁干净我们的贴…

云渲染3ds Max过程中,本地电脑可以断网或关机吗?

云渲染在近年来被越来越多的设计师所采用&#xff0c;因为它可以显著提高渲染速度&#xff0c;节省大量时间和精力。然而&#xff0c;一些用户不清楚云渲染的工作原理&#xff0c;也不知道在使用3ds Max、Maya等软件进行云渲染时&#xff0c;我们的本地电脑是否可以断网或关机。…

网络爬虫代理ip有什么好处?爬虫工作使用代理IP有哪些优势?

在爬虫工作中&#xff0c;使用代理IP有很多好处&#xff0c;可以帮助爬虫程序更加高效地完成任务。以下是使用代理IP的几个优势&#xff1a; 1. 增加匿名性 使用代理IP可以隐藏爬虫程序的真正IP地址&#xff0c;增加匿名性&#xff0c;避免被目标网站封禁。通过代理IP&#xff…

专门为Web应用程序提供安全保护的设备-WAF

互联网网站面临着多种威胁&#xff0c;包括网络钓鱼和人为的恶意攻击等。这些威胁可能会导致数据泄露、系统崩溃等严重后果。 因此&#xff0c;我们需要采取更多有效的措施来保护网站的安全。其中WAF&#xff08;Web application firewall&#xff0c;Web应用防火墙&#xff0…

边缘计算多角色智能计量插座:用电监测和资产管理的未来智能化引擎

目前主流的智能插座涵盖了红外遥控&#xff08;控制空调和电视等带有红外标准的电器&#xff09;&#xff0c;配备着测温、测湿等仓库应用场景&#xff0c;配备了人体红外或者毫米波雷达作为联动控制&#xff0c;但是大家有没有思考一个问题&#xff0c;就是随着对接的深入&…

CentOS7安装Xrdp以便Windows远程桌面连接

Centos7已经安装了桌面环境&#xff0c;想要Windows系统远程连接到桌面。 1&#xff0c;which vncserver 如果返回no vncserver,则需要安装 2&#xff0c;yum -y install tigervnc* 3&#xff0c;安装Xrdp yum install epel* -y yum --enablerepoepel -y install xrdp 4…

ruoyi-vue前端数据字典值引用与回显(列表中回显,多选框回显)

1. 列表中回显&#xff1a; 代码&#xff1a; <el-table v-if"refreshTable" v-loading"loading" :data"deptList" row-key"deptId" :default-expand-all"isExpandAll" :tree-props"{children: children, hasChil…

网络安全(黑客技术)-高效自学

1.网络安全是什么 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 2.网络安全市场 一、是市场需求量高&#xff1b; 二、则是发展相对成熟…

【云备份|| 日志 day5】文件热点管理模块

云备份day5 热点管理模块 热点管理模块 服务器端的热点文件管理是对上传的非热点文件进行压缩存储&#xff0c;节省磁盘空间。 而热点文件的判断在于上传的文件的最后一次访问时间是否在热点判断时间之内&#xff0c;比如如果一个文件一天都没有被访问过我们就认为这是一个非…

c++ 信奥编程 1129:统计数字字符个数

#include<bits/stdc.h> using namespace std; int main() {string arr; //定义变量 arr getline(cin, arr); //通过函数输入并存储到变量中 int a 0; // 定义变量a&#xff0c;并赋初值0for(int i 0; i < arr.length(); i){ if(arr[i] < 57 && arr[i] &…

2023年【北京市安全员-A证】最新解析及北京市安全员-A证复审模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年北京市安全员-A证最新解析为正在备考北京市安全员-A证操作证的学员准备的理论考试专题&#xff0c;每个月更新的北京市安全员-A证复审模拟考试祝您顺利通过北京市安全员-A证考试。 1、【多选题】《中华人民共和…

【C语法学习】20 - 文件访问顺序

文章目录 0 前言1 文件位置指示符2 rewind()2.1 函数原型2.2 参数2.3 返回值2.4 使用说明 3 ftell()函数3.1 函数原型3.2 参数3.3 返回值 4 fseek()4.1 函数原型4.2 参数4.3 返回值 5 示例5.1 示例15.2 示例2 0 前言 C语言文件访问分为顺序文件访问和随机文件访问。 1 文件位…

「Verilog学习笔记」使用子模块实现三输入数的大小比较

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 分析 题目要求编写子模块实现两个输入数的大小比较并输出较小值&#xff0c;可以使用if-else语句实现。同时要求在主模块中实现三个输入数值的大小比较&#xff0c;假设三个…

cortex-A7核 中断实验(按键中断实验)

1.选择按键触发方式 下降沿 2.解决消抖的方法 1&#xff09;ARM中&#xff1a;延时消抖 2&#xff09;linux驱动开发&#xff1a;定时器函数 3.框图 内部流程框图&#xff1a; 需要RCC GPIO EXTI GIC章节 中断触发流程&#xff1a; 4.RCC 章节 1&#xff09;使能GPIOF组 …

可root设备复制文件到system目录或者子目录下

目标或问题&#xff1a; 在可root的设备中&#xff0c;如何将某个文件拷贝到system/xxxx/xxxx的系统目录下&#xff1f; 解决方法&#xff1a; 首先依次执行以下命令&#xff1a; adb root adb remount 出现如下图所示&#xff1a; 然后执行复制文件推送到设备的命令即可&…

代码解释【待解决】

这里写目录标题 代码解释数组转化为列表&#xff0c;方便在哪里yeildrange()函数还有一些常用的小技巧。在这里我们列举两个常用技巧&#xff0c;以供参考梯度l.sum().backward()的粗浅理解detatch文字描述在默认情况下&#xff0c;PyTorch会累积梯度&#xff0c;我们需要清除之…

Go cobra简介

当你需要为你的 Go 项目创建一个强大的命令行工具时&#xff0c;你可能会遇到许多挑战&#xff0c;比如如何定义命令、标志和参数&#xff0c;如何生成详细的帮助文档&#xff0c;如何支持子命令等等。为了解决这些问题&#xff0c;github.com/spf13/cobra 就可以派上用场。 g…

ESP32 C3 smartconfig一键配网报错

AP配网 在调试我的esp32c3的智能配网过程中&#xff0c;发现ap配网使用云智能App是可以正常配置的。 切记用户如果在menu菜单里使能AP配网&#xff0c;默认SSID名字为adh_PK值_MAC后6位。用户可以修改这个apssid的键值&#xff0c;但是要使用云智能app则这个名字的开头必须为ad…

asp.net外卖网站系统VS开发mysql数据库web结构c#编程Microsoft Visual Studio

一、源码特点 asp.net外卖网站系统 是一套完善的web设计管理系统&#xff0c;系统采用mvc模式&#xff08;BLLDALENTITY&#xff09;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为mysql&#xff0c;使用c#语…

不同访问修饰符的访问数据权限的区别

在Java中&#xff0c;有四种访问修饰符&#xff1a;public、private、protected和默认修饰符。它们的作用是控制类、变量和方法的可见性&#xff0c;也就是说它们控制了哪些代码可以访问某个类、变量或方法的数据成员。 public&#xff1a;可以被任何类访问&#xff0c;对外部…