[C++&Qt] 通过信号与槽传递数据

简介: [C++&Qt] 通过信号与槽传递数据

一. 前言

Qt视觉项目中,一般需要用到信号和槽机制主要有两个地方:

  1. 软件功能模块Qt界面的各个控件进行交互的时候,需要使用信号和槽机制来完成信息的传递。
  2. 视觉算法模块上位机代码之间的信息传递需要通过信号和槽的机制来完成。

上面两者信号传递的方式本质是一样的,都是通过信号和槽的方式来完成信号的传递与接收,不同点就是前者的Qt控件的触发信号是Qt内部定义好的,我们定义一个槽函数直接用就可以;而后者各个类之间的信息传递是需要我们手动定义信号与槽函数来完成。


二. Qt界面控件信号传递

这里基本上都是和Qt界面上的一些按钮、复选框、编辑框等控件产生的触发信号,可以定义一个槽函数接收信号,也可以直接在connect链接信号与槽时,直接完成信号的接收与处理:

按钮QPushButton

connect(ui.pushButton_compute, &QPushButton::clicked, this, [=]() {
        //槽函数实现
    return;
  }

单选按钮QRadioButton

connect(ui.radioButton_imageLocate, &QRadioButton::toggled, this, [=](bool state) {
    //槽函数实现
    ui.widget_view->clearImage();
    ui.comboBox->clear();    
    if (m_imageViewLocate.size() > 0) {
        for (int index = 0; index < m_imageViewLocate.size(); index++){
        ui.comboBox->addItem(QString::number(index + 1, 10));
        }
        ui.comboBox->setCurrentIndex(m_imageID);
        ui.widget_view->setImage(m_imageViewLocate.at(m_imageID));
    }
});

下拉框QComboBox

connect(ui.cmbAffineType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [=](int index) {
    //槽函数实现
  int mFlag = index;
  ui.cmbAffineType->setItemData(1, "v", Qt::UserRole - 1); //设置第二行不可选中
});

计数器QSpinBox

connect(ui->spinBox_colNum, QOverload<int>::of(&QSpinBox::valueChanged),this, [=](int value)
{
    //槽函数实现
    int mFlag = value;
});

浮点计数器QDoubleSpinBox

connect(ui.spbGlueAreaRatio_2, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, [=](double value){
    //槽函数实现
    int mFlag = value;
});

三. 自定义信号传递

下面重点介绍一些第二种信号传递的方式,它涉及到了各个类之间的信号传递与接收

3.1. 信号传递单类型数据(适用于传递的数据较少的情况)

功能需求:在视觉库中通过信号的形式传两个double类型的数据给上位机项目代码

代码逻辑

  • 在基类MU_InspUiBase中定义信号,派生类GetMountOffset的槽函数中发送信号(各个派生类(包含GetMountOffset)继承基类MU_InspUiBase,所以在基类MU_InspUiBase中声明信号就相当于在各个子类中声明)
  • 在看项目代码中各个类之间的包含关系,我这里是基类数据MU_InspUiBase会传递到类MainUI中,再由类MainUI中传递到与软件的接口类VisionUI中,最终上位机软件接收类VisionUI中信号。

这里说的啰嗦了一点主要是想告诉大家,在信号传递之前要搞清楚代码中各个类之间的逻辑关系,才能层层递进完成信号的传递。

具体流程如下:

1、基类MU_InspUiBase中定义信号

class MU_InspUiBase : public QWidget
{
  Q_OBJECT
signals:
    void SIG_calculateOffSetOK(double x, double y);
};

2、基类MU_InspUiBase的派生类GetMountOffset中发送信号

#include "MU_InspUiBase.h"
GetMountOffset::GetMountOffset(const char* _path, QWidget *parent)
  : MU_InspUiBase(parent)
{
    emit SIG_calculateOffSetOK(x, y);
}

3、类MainUI中接收类GetMountOffset发送的信号

#include"MU_InspUiBase.h"
class MF_VISIONUI_EXPORT MainUI : public QWidget
{
  Q_OBJECT
signals:
    void SIG_calculateOffSetOK(double x, double y);
private:  
  MU_InspUiBase *m_InspUi = nullptr;
};
//.cpp
MainUI::MainUI(const char* _filePath, VISIONOPERATETYPE _functionOption, QWidget *parent)
  : QWidget(parent)
{
m_InspUi = new GetMountOffset(_filePath);
connect(m_InspUi, &MU_InspUiBase::SIG_calculateOffSetOK, [this](double x, double y)
{
    emit SIG_calculateOffSetOK(x, y);
});
}

4、软件的接口类VisionUI中重复上面的步骤:定义信号、接收信号、在发送信号,最终由上位机代码中接收该信号,获取其参数值。

注:判断信号有没有发送成功时,可以在connect处加个断点,打印一串代码,看看最终是否打印出来,如:

connect(m_InspUi, &MU_InspUiBase::SIG_calculateOffSetOK, [this](double x, double y)
{
  qDebug() << "yyyyyy";
});

3.2 信号传递自定义结构体数据(适用于传递的数据较多的情况)

1、定义结构体,使用宏Q_DECLARE_METATYPE,向QT声明这个结构体

#include <QVariant>
struct MS_MountOffset_SigResult
{
  MS_MountOffset_SigResult() :m_offsetX(0), m_offsetY(0)
  {}
  double m_offsetX;     //X方向补偿
  double m_offsetY;     //Y方向补偿
};
Q_DECLARE_METATYPE(MS_MountOffset_SigResult);

注:

①宏Q_DECLARE_METATYPE作用:对于自定义的结构体参数,信号槽无法识别参数,导致信号槽连接不起作用。所以需要在结构体中声明结束的地方加上结构体注册。

②自定义类型中一定要有默认构造函数,如果已经显式的定义了带有无默认参数的构造函数则需要另外写上默认构造函数 Test(){}。

③最好在类定义的头文件中加上#include < QVariant>,保证编译器能够识别该宏,否则可能会报错“错误提示: error C4430: 缺少类型说明符 - 假定为 int。”

2、定义信号和槽 — signals&slots

signals:
void SIG_calculateOffSetOK(QVariant VarDetailInfo);
slot:
void slot_calculateOffSetOK(QVariant VarDetailInfo);
QObject::connect(m_InspUi, SIGNAL(&SIG_calculateOffSetOK(QVariant)), this,
      SLOT(&slot_calculateOffSetOK(QVariant)), Qt::QueuedConnection);

3、在发送信号的位置将自定义结构类型封装成QVariant的形式

QVariant m_DataVar;
m_DataVar.setValue(m_MountOffset_SigResult);
emit SIG_calculateOffSetOK(m_DataVar);

注:m_MountOffset_SigResult为定义的结构体MS_MountOffset_SigResult的对象。

4、在接收信号的位置从封装中取出结构体参数

MS_MountOffset_SigResult m_MountOffset_SigResul_2;
m_MountOffset_SigResul_2 = m_DataVar.value<MS_MountOffset_SigResult>();//m_DataVar为上面QVariant的对象

下雨天,最惬意的事莫过于躺在床上静静听雨,雨中入眠,连梦里也长出青苔。


相关实践学习
基于Hologres轻量实时的高性能OLAP分析
本教程基于GitHub Archive公开数据集,通过DataWorks将GitHub中的项⽬、行为等20多种事件类型数据实时采集至Hologres进行分析,同时使用DataV内置模板,快速搭建实时可视化数据大屏,从开发者、项⽬、编程语⾔等多个维度了解GitHub实时数据变化情况。
阿里云实时数仓实战 - 用户行为数仓搭建
课程简介 1)学习搭建一个数据仓库的过程,理解数据在整个数仓架构的从采集、存储、计算、输出、展示的整个业务流程。 2)整个数仓体系完全搭建在阿里云架构上,理解并学会运用各个服务组件,了解各个组件之间如何配合联动。 3&nbsp;)前置知识要求:熟练掌握 SQL 语法熟悉 Linux 命令,对 Hadoop 大数据体系有一定的了解 &nbsp; 课程大纲 第一章&nbsp;了解数据仓库概念 初步了解数据仓库是干什么的 第二章&nbsp;按照企业开发的标准去搭建一个数据仓库 数据仓库的需求是什么 架构 怎么选型怎么购买服务器 第三章&nbsp;数据生成模块 用户形成数据的一个准备 按照企业的标准,准备了十一张用户行为表 方便使用 第四章&nbsp;采集模块的搭建 购买阿里云服务器 安装 JDK 安装 Flume 第五章&nbsp;用户行为数据仓库 严格按照企业的标准开发 第六章&nbsp;搭建业务数仓理论基础和对表的分类同步 第七章&nbsp;业务数仓的搭建&nbsp; 业务行为数仓效果图&nbsp;&nbsp;
目录
相关文章
|
编译器
(9)Qt中信号与槽重载的解决方案
本文介绍了在Qt中处理信号与槽重载问题的三种解决方案:使用函数指针、Qt提供的QOverload类和Qt4的宏方式。
866 3
|
11月前
|
存储 监控 算法
基于 C++ 哈希表算法实现局域网监控电脑屏幕的数据加速机制研究
企业网络安全与办公管理需求日益复杂的学术语境下,局域网监控电脑屏幕作为保障信息安全、规范员工操作的重要手段,已然成为网络安全领域的关键研究对象。其作用类似网络空间中的 “电子眼”,实时捕获每台电脑屏幕上的操作动态。然而,面对海量监控数据,实现高效数据存储与快速检索,已成为提升监控系统性能的核心挑战。本文聚焦于 C++ 语言中的哈希表算法,深入探究其如何成为局域网监控电脑屏幕数据处理的 “加速引擎”,并通过详尽的代码示例,展现其强大功能与应用价值。
217 2
(8)Qt中的自定义信号
本文介绍了如何在Qt框架中创建和使用自定义信号,并通过一个父子窗口切换的示例来展示自定义信号的实现和应用。
535 3
(8)Qt中的自定义信号
|
12月前
|
存储 C++
UE5 C++:自定义Http节点获取Header数据
综上,通过为UE5创建一个自定义HTTP请求类并覆盖GetResult方法,就能成功地从HTTP响应的Header数据中提取信息。在项目中使用自定义类,不仅可以方便地访问响应头数据,也可随时使用这些信息。希望这种方法可以为你的开发过程带来便利和效益。
458 35
|
12月前
|
SQL 数据库连接 数据库
在C++的QT框架中实现SQLite数据库的连接与操作
以上就是在C++的QT框架中实现SQLite数据库的连接与操作的基本步骤。这些步骤包括创建数据库连接、执行SQL命令、处理查询结果和关闭数据库连接。在实际使用中,你可能需要根据具体的需求来修改这些代码。
746 14
|
算法 Serverless 数据处理
从集思录可转债数据探秘:Python与C++实现的移动平均算法应用
本文探讨了如何利用移动平均算法分析集思录提供的可转债数据,帮助投资者把握价格趋势。通过Python和C++两种编程语言实现简单移动平均(SMA),展示了数据处理的具体方法。Python代码借助`pandas`库轻松计算5日SMA,而C++代码则通过高效的数据处理展示了SMA的计算过程。集思录平台提供了详尽且及时的可转债数据,助力投资者结合算法与社区讨论,做出更明智的投资决策。掌握这些工具和技术,有助于在复杂多变的金融市场中挖掘更多价值。
516 12
|
存储 监控 算法
公司监控上网软件架构:基于 C++ 链表算法的数据关联机制探讨
在数字化办公时代,公司监控上网软件成为企业管理网络资源和保障信息安全的关键工具。本文深入剖析C++中的链表数据结构及其在该软件中的应用。链表通过节点存储网络访问记录,具备高效插入、删除操作及节省内存的优势,助力企业实时追踪员工上网行为,提升运营效率并降低安全风险。示例代码展示了如何用C++实现链表记录上网行为,并模拟发送至服务器。链表为公司监控上网软件提供了灵活高效的数据管理方式,但实际开发还需考虑安全性、隐私保护等多方面因素。
256 0
公司监控上网软件架构:基于 C++ 链表算法的数据关联机制探讨
|
存储 算法 搜索推荐
【C++面向对象——群体类和群体数据的组织】实现含排序功能的数组类(头歌实践教学平台习题)【合集】
1. **相关排序和查找算法的原理**:介绍直接插入排序、直接选择排序、冒泡排序和顺序查找的基本原理及其实现代码。 2. **C++ 类与成员函数的定义**:讲解如何定义`Array`类,包括类的声明和实现,以及成员函数的定义与调用。 3. **数组作为类的成员变量的处理**:探讨内存管理和正确访问数组元素的方法,确保在类中正确使用动态分配的数组。 4. **函数参数传递与返回值处理**:解释排序和查找函数的参数传递方式及返回值处理,确保函数功能正确实现。 通过掌握这些知识,可以顺利地将排序和查找算法封装到`Array`类中,并进行测试验证。编程要求是在右侧编辑器补充代码以实现三种排序算法
371 5
|
C++
003 Qt_信号和槽-上
本文介绍了Qt中的信号与槽机制,包括信号和槽的概念、本质及连接方法,并演示了如何自定义槽函数。信号是事件的体现,槽是对信号的响应函数。通过信号与槽,可以将独立的控件关联起来,实现复杂的交互逻辑。文中还详细展示了如何在Qt项目中定义和使用槽函数,通过实例代码和图形化界面操作,帮助读者更好地理解和应用这一机制。
408 1
003 Qt_信号和槽-上
|
传感器 安全
第四问:QT中信号和槽原理
Qt的信号与槽机制是观察者模式的典型实现,允许对象间通信而不直接依赖。信号用于通知事件发生,槽是响应信号的函数,通过`QObject::connect()`连接。这种机制实现了松耦合、灵活扩展和自动通知,适用于UI更新和数据绑定等场景。

推荐镜像

更多
  • qt