第六篇 在ROS工程中使用QT开发界面笔记之--混用线程和信号槽机制

2023-11-14

有个新任务,需要显示sub到的数据内容,看起来挺简单的,毕竟原来那个工程采用zmq数据流的发送与接收时用到了启动新线程接收数据的方法。照搬肯定不行,因为有区别:原来工程直接在新线程里面持续接收数据,与界面的主线程没有关系。现在这种要用界面sub数据必须在主线程上启ROS节点不停的sub,与主线程本身的阻塞显示任务就冲突了,而且还要实现将收到的数据在界面上不断刷新的任务。

看来问题只能一个一个解决了。

解决第一个问题:主线程启动ROS节点持续sub和界面持续显示存在的冲突

解决办法:在ROS节点的cpp函数中创建界面实例并将其设置为主线程,将界面运行的代码放到这里。将callback函数放在实例化界面时实现,在界面的构造函数中启个新线程,将ROS的spin函数放在里面,搞定。

// show_node.cpp 节点名称就是 show_node
#include <ros/ros.h>
#include "form.h"
#include <QApplication>
#include "std_msgs/Int32.h"
int main(int argc, char **argv)
{
 ros::init(argc, argv, "show_node");//初始化 show_node节点
 QApplication a(argc, argv);
 // 创建 Form 实例
 Form form(nullptr);
 ros::NodeHandle nh;
 ros::Subscriber subdata = nh.subscribe<std_msgs::Int32>("pubdata", 10, boost::bind(&Form::staticShowCallback, _1, &form));//订阅话题 pubdata
 form.show();
 return a.exec();
}
界面Form的构造函数中添加callback函数的实现内容:
创建新线程,在头文件中定义
#include <thread>
…
class Form : public QWidget
{
 Q_OBJECT
public:
...
private:
 Ui::Form *ui;
 std::thread rosthread;
};
在cpp文件中的构造函数中使用
Form::Form(QWidget *parent) :
 QWidget(parent),
 ui(new Ui::Form)
{
…

 rosthread =std::thread(&Form::getrosdata,this);

}
将spin放在这个函数里面,就可以让sub运行在新的线程里面一直sub不停。
void Form::getrosdata()
{
 ros::spin(); // Handle ROS callbacks in the separate thread
}
当然还是要停,什么时候界面退出了就停止sub,所以放这里
Form::~Form()
{
 rosthread.join(); // Wait for the ROS thread to finish
 delete ui;
} show_node.cpp 节点名称就是 show_node
#include <ros/ros.h>
#include "form.h"
#include <QApplication>
#include "std_msgs/Int32.h"
int main(int argc, char **argv)
{
 ros::init(argc, argv, "show_node");//初始化 show_node节点
 QApplication a(argc, argv);
 // 创建 Form 实例
 Form form(nullptr);
 ros::NodeHandle nh;
 ros::Subscriber subdata = nh.subscribe<std_msgs::Int32>("pubdata", 10, boost::bind(&Form::staticShowCallback, _1, &form));//订阅话题 pubdata
 form.show();
 return a.exec();
}
界面Form的构造函数中添加callback函数的实现内容:
创建新线程,在头文件中定义
#include <thread>
…
class Form : public QWidget
{
 Q_OBJECT
public:
...
private:
 Ui::Form *ui;
 std::thread rosthread;
};
在cpp文件中的构造函数中使用
Form::Form(QWidget *parent) :
 QWidget(parent),
 ui(new Ui::Form)
{
…

 rosthread =std::thread(&Form::getrosdata,this);

}
将spin放在这个函数里面,就可以让sub运行在新的线程里面一直sub不停。
void Form::getrosdata()
{
 ros::spin(); // Handle ROS callbacks in the separate thread
}
当然还是要停,什么时候界面退出了就停止sub,所以放这里
Form::~Form()
{
 rosthread.join(); // Wait for the ROS thread to finish
 delete ui;
}

解决第二个问题:用sub到的数据不停的刷新界面的显示数据内容

不停的刷新?难道又要启动一个线程?可是界面显示是在主线程里面做的啊。

解决办法:用QT自带的信号槽机制。信号槽机制的本质是当事件产生或者信号到来的时候就运行槽函数,不管什么时候运行多少次,别忘了这个运行的程序是在主线程中的,正好能够完美解决我们的问题。信号就用QT自带的定时器QTimer,简单好用,指定个结束时间让定时器不停的启动结束启动结束,每次结束就去调槽函数,用接收到的数据刷新界面显示的数据。

生成界面的主程序中添加:

 timers = new QTimer(this);
 timers->start(200);
 connect(timers, SIGNAL(timeout()), this, SLOT(updateSlot()));timers = new QTimer(this);
 timers->start(200);
 connect(timers, SIGNAL(timeout()), this, SLOT(updateSlot()));

定义void Form::updateSlot()

{
 timeshow->setText(QString::number(ourtime)+" 秒");
 countshow->setText(QString::number(outcount));
 othertime->setText(QString::number(theirtime)+" 秒");
 othercount->setText(QString::number(thericount));
}
 timeshow->setText(QString::number(ourtime)+" 秒");
 countshow->setText(QString::number(outcount));
 othertime->setText(QString::number(theirtime)+" 秒");
 othercount->setText(QString::number(thericount));
}

perfect!


                
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

第六篇 在ROS工程中使用QT开发界面笔记之--混用线程和信号槽机制 的相关文章

  • WPF DataGrid 多选

    我读过几篇关于这个主题的文章 但很多都是来自 VS 或框架的早期版本 我想做的是从 dataGrid 中选择多行并将这些行返回到绑定的可观察集合中 我尝试创建一个属性 类型 并将其添加到可观察集合中 它适用于单个记录 但代码永远不会触发多个
  • 如何将 std::string& 转换为 C# 引用字符串

    我正在尝试将 C 函数转换为std string参考C 我的 API 如下所示 void GetStringDemo std string str 理想情况下 我希望在 C 中看到类似的东西 void GetStringDemoWrap r
  • 没有特殊字符的密码验证器

    我是 RegEx 的新手 已经进行了大量搜索 但没有找到任何具体内容 我正在编写一个验证密码字符串的正则表达式 可接受的字符串必须至少具有 4 种字符类型中的 3 种 数字 小写字母 大写字母 特殊字符 我对包含有一个想法 也就是说 如果这
  • 在一个数据访问层中处理多个连接字符串

    我有一个有趣的困境 我目前有一个数据访问层 它必须与多个域一起使用 并且每个域都有多个数据库存储库 具体取决于所调用的存储过程 目前 我只需使用 SWITCH 语句来确定应用程序正在运行的计算机 并从 Web config 返回适当的连接字
  • 通过引用传递 [C++]、[Qt]

    我写了这样的东西 class Storage public Storage QString key const int value const void add item QString int private QMap
  • C++11 删除重写方法

    Preface 这是一个关于最佳实践的问题 涉及 C 11 中引入的删除运算符的新含义 当应用于覆盖继承父类的虚拟方法的子类时 背景 根据标准 引用的第一个用例是明确禁止调用某些类型的函数 否则转换将是隐式的 例如最新版本第 8 4 3 节
  • std::vector 与 std::stack

    有什么区别std vector and std stack 显然 向量可以删除集合中的项目 尽管比列表慢得多 而堆栈被构建为仅后进先出的集合 然而 堆栈对于最终物品操作是否更快 它是链表还是动态重新分配的数组 我找不到关于堆栈的太多信息 但
  • free 和 malloc 在 C 中如何工作?

    我试图弄清楚如果我尝试 从中间 释放指针会发生什么 例如 看下面的代码 char ptr char malloc 10 sizeof char for char i 0 i lt 10 i ptr i i 10 ptr ptr ptr pt
  • 无限循环与无限递归。两者都是未定义的吗?

    无副作用的无限循环是未定义的行为 看here https coliru stacked crooked com view id 24e0a58778f67cd4举个例子参考参数 https en cppreference com w cpp
  • 用于 FTP 的文件系统观察器

    我怎样才能实现FileSystemWatcherFTP 位置 在 C 中 这个想法是 每当 FTP 位置添加任何内容时 我都希望将其复制到我的本地计算机 任何想法都会有所帮助 这是我之前问题的后续使用 NET 进行选择性 FTP 下载 ht
  • C# 列表通用扩展方法与非通用扩展方法

    这是一个简单的问题 我希望 集合类中有通用和非通用方法 例如List
  • 使用 C# 中的 CsvHelper 将不同文化的 csv 解析为十进制

    C 中 CsvHelper 解析小数的问题 我创建了一个从 byte 而不是文件获取 csv 文件的类 并且它工作正常 public static List
  • 为什么这个字符串用AesCryptoServiceProvider第二次解密时不相等?

    我在 C VS2012 NET 4 5 中的文本加密和解密方面遇到问题 具体来说 当我加密并随后解密字符串时 输出与输入不同 然而 奇怪的是 如果我复制加密的输出并将其硬编码为字符串文字 解密就会起作用 以下代码示例说明了该问题 我究竟做错
  • 为什么 C# 2.0 之后没有 ISO 或 ECMA 标准化?

    我已经开始学习 C 并正在寻找标准规范 但发现大于 2 0 的 C 版本并未由 ISO 或 ECMA 标准化 或者是我从 Wikipedia 收集到的 这有什么原因吗 因为编写 审查 验证 发布 处理反馈 修订 重新发布等复杂的规范文档需要
  • 如何实例化 ODataQueryOptions

    我有一个工作 简化 ODataController用下面的方法 public class MyTypeController ODataController HttpGet EnableQuery ODataRoute myTypes pub
  • 有没有办法让 doxygen 自动处理未记录的 C 代码?

    通常它会忽略未记录的 C 文件 但我想测试 Callgraph 功能 例如 您知道在不更改 C 文件的情况下解决此问题的方法吗 设置变量EXTRACT ALL YES在你的 Doxyfile 中
  • 对于某些 PDF 文件,LoadIFilter() 返回 -2147467259

    我正在尝试使用 Adob e IFilter 搜索 PDF 文件 我的代码是用 C 编写的 我使用 p invoke 来获取 IFilter 的实例 DllImport query dll SetLastError true CharSet
  • 为什么 std::uint32_t 与 uint32_t 不同?

    我对 C 有点陌生 我有一个编码作业 很多文件已经完成 但我注意到 VS2012 似乎有以下语句的问题 typedef std uint32 t identifier 不过 似乎将其更改为 typedef uint32 t identifi
  • 在OpenGL中,我可以在坐标(5, 5)处精确地绘制一个像素吗?

    我所说的 5 5 正是指第五行第五列 我发现使用屏幕坐标来绘制东西非常困难 OpenGL 中的所有坐标都是相对的 通常范围从 1 0 到 1 0 为什么阻止程序员使用屏幕坐标 窗口坐标如此严重 最简单的方法可能是通过以下方式设置投影以匹配渲
  • 使用 WGL 创建现代 OpenGL 上下文?

    我正在尝试使用 Windows 函数创建 OpenGL 上下文 现代版本 基本上代码就是 创建窗口类 注册班级 创建一个窗口 choose PIXELFORMATDESCRIPTOR并设置它 创建旧版 OpenGL 上下文 使上下文成为当前

随机推荐

  • 错误使用 network/subsasgn>network_subsasgn (line 550) net.IW{1,1} must be a 16-by-19 matrix. 出错 network

    该代码为基于PSO和BP网络的预测 清空环境 clc clear 读取数据 load CHE2 mat 节点个数 inputnum 17 hiddennum 16 outputnum 1 训练数据和预测数据 input train inpu
  • mysql 集群 一主两从环境测试,MHA主备切换

    目录 前言 1 相关安装文件 2 虚拟机 mysql数据库安装 2 1 安装VMware 15 以及 linux 操作系统 2 2 安装mysql数据库 2 2 1安装环境准备 2 2 2 mysql 数据库安装 2 3 克隆centos虚
  • Cmake零基础教程——常用语法命令

    编译选项 在cmake脚本中 设置编译选项有两种方式 1 可以通过add compile options命令 2 也可以通过set命令修改CMAKE CXX FLAGS或CMAKE C FLAGS 存在即合理 那么使用这两种方式存在怎样的区
  • ssh和ftp登录的几种方式

    ssh登录的几种方式 本文为https www bilibili com video av755468030 笔记 1 密码账号登录 ssh p 1234 name 目标ip p 为指定端口 name为用户名 2 使用公钥私钥登录 获取指定
  • IDEA中javaweb项目导入外部jar包

    IDEA中javaweb项目导入外部jar包 打开Project Structure 选中Modules 选择Dependencies 点击 选择要导入的jar包或jar包文件夹 选中要使用的jar包或jar包文件夹 点击ok 如果只是按照
  • excel导出功能

    安装excel所需依赖和按需加载 由于 Export2Excel不仅依赖js xlsx还依赖file saver和script loader 所以你先需要安装如下命令 npm install xlsx file saver S npm in
  • React传参和定义变量

    react 声明变量 react传参
  • 学习linux内核的经典书籍介绍

    有关内核的书籍可以用汗牛充栋来形容 不过只有一些经典的神作经住了考验 首先是5本久经考验的神作 个人概括为 2 1 2 第一个2是指2本全面讲解内核的书 中间的1指1本讲解驱动开发的书 后面的2则指2本有关内核具体子系统的书 你是否想到了某
  • vscode 静态语法检测插件C/C++ Advanced Lint,ubuntu20.04安装clang、cppcheck

    远程环境 ubuntu20 04 本地开发环境 windows 11 开发IDE vscode 一 ubuntu20 04安装clang 安装llvm apt get install llvm 2 安装clang apt get insta
  • 11-数据结构-双链表的创建-输出-初始化-插入-删除

    问题 双链表的创建 输出 初始化 插入 删除 思路 搞清楚双链表是怎么样的 多了一个前指针 此外每次链接的时候 都是先连接好后面的再连接前面的 直接看代码吧 代码如下 include
  • 思科实验 voip通信的配置(内附命令超详细)

    作者 小刘在C站 个人主页 小刘主页 每天分享云计算网络运维课堂笔记 努力不一定有回报 但一定会有收获加油 一起努力 共赴美好人生 夕阳下 是最美的绽放 树高千尺 落叶归根人生不易 人间真情 目录 一 实验目的和要求 二 实验设备
  • Python疫情数据爬取与可视化

    使用Python爬取腾讯新闻疫情数据 并使用pyecharts可视化 绘制增长人数地图 柱状图 折线图 文章目录 1 分析网页 2 导入模块 3 抓取数据 4 提取数据并写入Excel 5 国内各地区现有确诊人数地图 6 国内各地区现有确诊
  • 秒懂边缘云

    作者 辰舒 章节内容 如何配置解析记录 已有CNAME A记录时如何配置 如何检查解析配置是否生效 解析基本原理 前言 上个章节中我们学习了如何根据业务情况添加CDN域名并配置源站 但在添加完成后 域名尚未真正接入CDN服务 我们需要将域名
  • Kafka

    1 概述 1 1 定义 Kafka是一个分布式的基于发布 订阅模式的消息队列 主要应用于大数据实时处理领域 优势 kafka可以做到 使用非常普通的硬件 也可以支持每秒数百万的消息读写 MQ 代表消息队列 kafka只是众多mq中一款产品
  • Shell脚本编程入门--Day2

    文章目录 几个简单内置shell命令 shell字串的语法 计算变量长度的各种玩法 批量修改文件名 特殊shell扩展变量 实际应用 父子shell 创建进程列表 创建子shell 几个简单内置shell命令 echo n 不换行输出 e
  • 牛客面试高频算法题js(最长无重复子数组、删除链表的倒数第n个节点、大数加法、按之字形顺序打印二叉树、链表相加(二))

    最长无重复子数组 描述 给定一个长度为n的数组arr 返回arr的最长无重复元素子数组的长度 无重复指的是所有数字都不相同 子数组是连续的 比如 1 3 5 7 9 的子数组有 1 3 3 5 7 等等 但是 1 3 7 不是子数组 数据范
  • Java并发基础:变量的线程安全

    一 变量的线程安全分析 成员变量和静态变量是否线程安全 如果它们没有共享 则线程安全 如果它们被共享了 根据它们的状态是否能够改变 又分两种情况 如果只有读操作 则线程安全 如果有读写操作 则这段代码是临界区 需要考虑线程安全 局部变量是否
  • 解决Windows Server 2012 R2无法远程桌面

    通常使用Windows Server 的远程桌面 我们自然是在配置中启用远程桌面 系统会默认将所需要的防火墙对应的入站协议启用 这样我们就可使用远程桌面了 但是如果您尝试了Windows Server 2012 R2后 或许会碰到和我一样的
  • range遍历 channel 的小坑

    package main import fmt sync var wg sync WaitGroup func main c make chan int 无缓冲 wg Add 1 go send c for i range c send 协
  • 第六篇 在ROS工程中使用QT开发界面笔记之--混用线程和信号槽机制

    有个新任务 需要显示sub到的数据内容 看起来挺简单的 毕竟原来那个工程采用zmq数据流的发送与接收时用到了启动新线程接收数据的方法 照搬肯定不行 因为有区别 原来工程直接在新线程里面持续接收数据 与界面的主线程没有关系 现在这种要用界面s