【QVariant类型剖析】

QVariant类型剖析

  • 🌟 官方文档中给出的定义
  • 🌟 特性
  • 🌸QVariant实战应用
  • 🌸项目成果展示

在这里插入图片描述

🌟 官方文档中给出的定义

📘Because C++ forbids unions from including types that have non-default constructors or destructors, most interesting Qt classes cannot be used in unions. Without QVariant, this would be a problem for QObject::property() and for database work, etc.
📖[译文]:由于C ++禁止联合(union)中引用具有自定义构造函数或析构函数的类型,因此这个最有趣的QT类并不能在联合(union)中使用。没有QVariant类的支持,Qt的属性系统和数据库将无法进行正常工作。

📘A QVariant object holds a single value of a single type() at a time. (Some type()s are multi-valued, for example a string list.) You can find out what type, T, the variant holds, convert it to a different type using convert(), get its value using one of the toT() functions (e.g., toSize()) and check whether the type can be converted to a particular type using canConvert().
📖[译文]:QVariant对象每次只能容纳唯一类型的唯一值。(ps: 一些类型是可以包含有多个值,例如:QStringList)。你可以弄清楚T是哪种类型,通过使用convert()转换为不同的类型,通过T()显示转换获取其容纳的值,并通过canConvert()来判断是否能够转换为对应的类型。

📘The methods named toT() (e.g., toInt(), toString()) are const. If you ask for the stored type, they return a copy of the stored object. If you ask for a type that can be generated from the stored type, toT() copies and converts and leaves the object itself unchanged. If you ask for a type that cannot be generated from the stored type, the result depends on the type; see the function documentation for details
📖[译文]:toT()是一个稳定的方法(例如,toInt()、toString())。如果您要求存储的类型,他们会返回存储对象的副本。如果您要求一个可以从存储的类型生成的类型,toT()会复制和转换对象,并保持对象本身不变。如果您要求一个无法从存储的类型生成的类型,结果取决于该类型;有关详细信息,请参阅功能文档

🌟 特性

QVariant 是Qt中用于封装任意类型数据的类,它可以在不同数据类型之间进行转换和存储,是Qt中处理数据的重要工具之一。

  • ✨数据类型的封装和存储QVariant 可以封装和存储几乎所有Qt支持的数据类型,包括基本数据类型(如整数、浮点数、布尔值、枚举)、复合数据类型(如字符串、列表、映射、日期时间)、自定义数据类型(通过注册元类型实现)等。
  QDataStream out(...);
  QVariant v(123);                // The variant now contains an int
  int x = v.toInt();              // x = 123
  out << v;                       // Writes a type tag and an int to out
  v = QVariant("hello");          // The variant now contains a QByteArray
  v = QVariant(tr("hello"));      // The variant now contains a QString
  int y = v.toInt();              // y = 0 since v cannot be converted to an int
  QString s = v.toString();       // s = tr("hello")  (see QObject::tr())
  out << v;                       // Writes a type tag and a QString to out
  ...
  QDataStream in(...);            // (opening the previously written stream)
  in >> v;                        // Reads an Int variant
  int z = v.toInt();              // z = 123
  qDebug("Type is %s",            // prints "Type is int"
          v.typeName());
  v = v.toInt() + 100;            // The variant now hold the value 223
  v = QVariant(QStringList());
  • ✨类型安全的数据访问QVariant 允许您以一种类型安全的方式访问封装的数据,而不需要显式的类型转换。您可以通过 QVariant::value() 将 QVariant 转换为指定类型 T 的值。
 QVariant var = 42;
 int intValue = var.value<int>(); // 获取整数值
  • ✨动态类型识别:Variant 可以存储数据的同时记录其实际类型信息,使得在运行时能够动态地识别和转换数据类型。您可以使用 QVariant::type() 方法获取存储的数据类型。
 QVariant var = "Hello";
 qDebug() << var.type(); // 输出数据类型
  • ✨空值表示:QVariant 可以表示空值(即无效值),这在处理可能没有值的情况时非常有用。您可以使用 QVariant::isNull() 或 QVariant::isValid() 方法检查 QVariant 是否为空或有效。
 QVariant var; // 未初始化的空值
 if (var.isNull()) {
     qDebug() << "Variant is null";
 }
  • ✨通用数据存储和传递:QVariant 在Qt中广泛用于通用数据的存储和传递,例如在信号和槽参数中传递任意类型的数据,或者在模型/视图框架中存储和操作各种类型的数据。下面是在QTreeView中设置一个节点的角色数据。
 //setData()函数为节点的某一列设置一个角色数据
 //其中column是列号role是角色的值, value是QVariant 类型的数。
 void QTreeWidgetItem::setData(int column , int role , const QVariant &value)
 //它为节点的第一列角色Qt::UserRole设置了字符串数据dataStr,Qt::UserRole是枚举类型Qt::ItemDataRole个预定义的值
 item >setData(MainWindow::colitem,Qt::UserRole,QVariant(dataStr)) ;
  • ✨元类型系统的支持:QVariant 和Qt的元类型系统(Meta Type System)密切相关。通过注册自定义类型到元类型系统,您可以使 QVariant 能够处理自定义的用户数据类型。
#include <QMetaType> // 包含Q_DECLARE_METATYPE宏所需的头文件
//可以通过下面这种方式声明元类型
Q_DECLARE_METATYPE("QVector<AgendaInfo>");

💫 补充说明:
在 Qt 中,Q_DECLARE_METATYPE 宏和 qRegisterMetaType 函数都是用于将自定义类型注册到 Qt 的元类型系统中,以便在信号槽、线程间通信等场景中能够正确地处理这些自定义类型的数据。虽然它们的作用相似,但在不同的情况下适合使用不同的方式。

  1. 💥Q_DECLARE_METATYPE 宏用于在编译时声明自定义类型作为元类型,以便 Qt 的元类型系统能够识别和处理该类型的数据。通常在自定义类型的声明之后,通过 Q_DECLARE_METATYPE 宏来告知 Qt 如何处理该类型。
  2. 💥qRegisterMetaType 函数用于在运行时动态注册自定义类型作为元类型。通常用于将自定义类型注册为 Qt 的信号槽系统中的参数类型,以便能够在不同线程间传递该类型的数据。
    在这里插入图片描述

🌸QVariant实战应用

  • 范例
    下面我利用QVariant来容纳一个自定义的数据类型ItemInfo,将其与QListWidget中的项(QListWidgetItem)关联起来,将其作为项的用户自定义角色的起始值(Qt::UserRole)的数据。实现主要项目功能如下:
    1. 💫通过QLineEdit(Qt提供的单行文本编辑器控件)来输入ItemInfo的成员变量的值。
 struct ItemInfo{//节点信息
     QString name;//节点名称
     QSize size;//节点大小
     QIcon icon;//节点图标
     ItemInfo(const QString &n = QString(), const QSize &s = QSize(),  const QIcon &i = QIcon())
        : name(n), size(s), icon(i)
     {}
 };
// 在结构体定义之后添加Q_DECLARE_METATYPE宏声明
Q_DECLARE_METATYPE(ItemInfo)

ItemInfo是用户自定义数据结构类型,必须通过声明元类型

  1. 💫通过QPushButton(Qt提供的普通按钮控件)来打开QFileDialog(文件选择对话框),选择Icon文件的路径,并将图片显示在QLabel中。
void widget::on_btn_Choose_clicked()
{
    // 选择节点图标文件
    QString fileName = QFileDialog::getOpenFileName(this, "Choose Icon"
                            , "D:/Repositories/PaperlessConferencePCSystem/src/Resources", "Icons (*.jpg;*.png)");

    if (!fileName.isEmpty()) {
        // 添加选择的图标文件到当前图标
        m_currentIcon.addFile(fileName);
        ui->lab_Icon->setPixmap(m_currentIcon.pixmap(50,50));
    }
}

其中getOpenFileName()函数是QFileDialog提供的静态函数,用于返回选中的文件名称。函数原型如下:

[static] QString QFileDialog::getOpenFileName(QWidget *parent = nullptr, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = nullptr, QFileDialog::Options options = Options())
  1. 💫通过QPushButton(Qt提供的普通按钮控件)来生成一个QListWidgetItem,并添加到QListView中,展示出与该Item关联的Icon、Name等信息。
void widget::on_btn_Add_clicked()
{
    // 获取用户输入的节点信息
    QString name = ui->lEdit_Name->text();
    int width = ui->lEdit_Width->text().toInt();
    int height = ui->lEdit_Height->text().toInt();

    // 创建节点信息结构体
    ItemInfo info(name, QSize(width, height), m_currentIcon);

    // 创建包含节点信息的 QListWidgetItem
    QListWidgetItem *item = new QListWidgetItem(info.icon, info.name);
    // 将 QListWidgetItem 添加到 QListWidget 中
    ui->listWidget->addItem(item);

    // 存储节点信息与 QListWidgetItem 的关联,可使用 QListWidgetItem 的 data() 方法存储
    QVariant variant;
    variant.setValue(info);
    item->setData(Qt::UserRole, variant); // 将节点信息存储到 QListWidgetItem 的 data 中
}
  1. 💫通过点击QListWidgetItem,通过QLabel显示出该Item关联的QSize信息。
void widget::on_listWidget_itemClicked(QListWidgetItem *item)
{
    // 获取点击的 QListWidgetItem 中存储的节点信息
    QVariant variant = item->data(Qt::UserRole);
    if (variant.canConvert<ItemInfo>()) {
        ItemInfo info = variant.value<ItemInfo>();

        // 显示节点的 QSize 信息
        QString sizeInfo = QString("Size: %1 x %2").arg(info.size.width()).arg(info.size.height());
        ui->lab_Status->setText("Item Size"+ sizeInfo);

        ui->lab_Icon->setPixmap(info.icon.pixmap(50,50));
    }
}

🌸项目成果展示

暂时支持图片展示效果,但我会将源码上传到GitHub[获取源码GitHub]。
进入软件

在这里插入图片描述
填上ItemInfo的信息,并点击AddItem
在这里插入图片描述
点击左侧中存在的Item
在这里插入图片描述
再添加一个item
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

(Java)心得:LeetCode——5.最长回文子串

一、原题 给你一个字符串 s&#xff0c;找到 s 中最长的回文子串。 如果字符串的反序与原始字符串相同&#xff0c;则该字符串称为回文字符串。 示例 1&#xff1a; 输入&#xff1a;s "babad" 输出&#xff1a;"bab" 解释&#xff1a;"aba"…

Java并发编程及并发包中类分析

一、并发编程线程基础&#xff1a; 1.什么是线程&#xff1a; 线程是进程中的一个实体&#xff0c;线程本身是不会独立存在的进程是代码在数据集合上的一 次运行活动 &#xff0c; 是系统进行资源分配和调度的基本单位 线程则是进程的 执行路径&#xff0c; 一 个进程中至少有…

2024年5月10日有感复盘

2024年5月10日有感复盘 时间 今天是一个很美好的一天&#xff0c;原因是很平凡&#xff0c;读书很平凡&#xff0c;玩游戏很平凡&#xff0c;然后生活很平凡&#xff0c;未来可期&#xff0c;听歌很舒服&#xff0c;很喜欢一个人呆在图书馆的感觉&#xff0c;很喜欢发呆&…

串口属性中的BM延时计时器问题

如果使用程序修改则需要修改注册表对应位置如下 第一个示例&#xff08;217&#xff09; 第二个示例&#xff08;219&#xff09; 需要注意的事情是修改前必须点查看串口名称&#xff08;例如上图是com5&#xff09; 程序修改&#xff1a; 有没有办法以编程方式更改USB <…

2024第十六届“中国电机工程学会杯”数学建模A题B题思路分析

文章目录 1 赛题思路2 比赛日期和时间3 竞赛信息4 建模常见问题类型4.1 分类问题4.2 优化问题4.3 预测问题4.4 评价问题 5 建模资料 1 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 2 比赛日期和时间 报名截止时间&#xff1a;2024…

vuex核心概念-actions

目录 一、概述 二、应用场景 三、使用步骤 三、注意 四、辅助函数-mapActions 一、概述 目标&#xff1a;明确actions的基本语法&#xff0c;处理异步操作。 需求&#xff1a;一秒钟之后&#xff0c;修改state的count成666。 说明&#xff1a;mutations必须是同步的(便于…

geotrust企业通配符证书2990

随着时代的变化&#xff0c;人们获取信息的方式由报纸、书籍变为手机、电脑&#xff0c;因此很多企事业单位用户开始在互联网中创建网站来进行宣传&#xff0c;吸引客户。为了维护网站安全环境&#xff0c;保护客户数据&#xff0c;企事业单位也开始使用SSL数字证书&#xff0c…

spfa检测负权回路C++

1.负权边回路首先dist数组刚开始初始化是0&#xff0c;&#xff08;因为是检测回路&#xff0c;那么无论从哪里开始起点都是一样的&#xff0c;所以一开始就会把所有点都加载到队列中&#xff0c;所以就相当于把dist[所有点] 0&#xff09;&#xff1b;下面就是cnt数组----很多…

LeetCode例题讲解:844.比较含退格的字符串

给定 s 和 t 两个字符串&#xff0c;当它们分别被输入到空白的文本编辑器后&#xff0c;如果两者相等&#xff0c;返回 true 。# 代表退格字符。 注意&#xff1a;如果对空文本输入退格字符&#xff0c;文本继续为空。 示例 1&#xff1a; 输入&#xff1a;s "ab#c&qu…

队列 + 宽搜(BFS)

目录 leetcode题目 一、二叉树的层序遍历 二、二叉树的层序遍历 II 三、N叉树的层序遍历 四、二叉树的锯齿形层序遍历 五、二叉树最大宽度 六、在每个树行中找最大值 七、二叉树的层平均值 八、最大层内元素和 九、二叉树的第K大层和 十、反转二叉树的奇数层 leetco…

P8803 [蓝桥杯 2022 国 B] 费用报销

P8803 [蓝桥杯 2022 国 B] 费用报销 分析 最值问题——DP 题意分析&#xff1a;从N张票据中选&#xff0c;且总价值不超过M的票据的最大价值&#xff08;背包问题&#xff09; K天限制 一、处理K天限制&#xff1a; 1.对于输入的是月 日的格式&#xff0c;很常用的方式是…

李宏毅-注意力机制详解

原视频链接&#xff1a;attention 一. 基本问题分析 1. 模型的input 无论是预测视频观看人数还是图像处理&#xff0c;输入都可以看作是一个向量&#xff0c;输出是一个数值或类别。然而&#xff0c;若输入是一系列向量&#xff0c;长度可能会不同&#xff0c;例如把句子里的…

【CTF Web】XCTF GFSJ0477 backup Writeup(备份文件+源码泄漏+目录扫描)

backup X老师忘记删除备份文件&#xff0c;他派小宁同学去把备份文件找出来,一起来帮小宁同学吧&#xff01; 解法 使用 dirsearch 扫描目录。 dirsearch -u http://61.147.171.105:49361/下载&#xff1a; http://61.147.171.105:64289/index.php.bak打开 index.php.bak&am…

一文读懂 RAG:它将如何重新定义 AI 的未来?

RAG 可以使 LLM 能够在实时请求提供事实信息时&#xff0c;访问外部来源的数据&#xff0c;比如经过审核的数据库或互联网上的信息。这样一来&#xff0c;RAG 就消除了大家对于 LLM 仅依赖其训练数据中获得的内部知识库的顾虑&#xff0c;毕竟&#xff0c;这些知识库可能存在缺…

论文研读 Disentangled Information Bottleneck

解耦信息瓶颈 摘要&#xff1a; 信息瓶颈方法是一种从源随机变量中提取与预测目标随机变量相关的信息的技术&#xff0c;通常通过优化平衡压缩和预测项的IB拉格朗日乘子f来实现&#xff0c;然而拉格朗日乘子很难优化&#xff0c;需要多次实验来调整拉格朗日乘子的值&#xff0c…

【TS】入门

创建项目 vscode自动编译ts 生成配置文件 tsc --init 然后发现终端也改变了&#xff1a;

飞跨电容型的三电平(FC-NPC)逆变器simulink仿真模型

本人搭建了飞跨电容型的三电平逆变器simulink仿真模型&#xff0c;相较于二极管钳位型三电平逆变器而言&#xff0c;钳位二极管变为飞跨的电容。采用SPWM调制和均流均压控制&#xff0c;通过搭建仿真模型得到三电平波形。 三电平拓扑中的飞跨电容是指在电路的输出端使用电容来实…

创建一个即时打印XML报表

即时打印的XML报表不需要创建PLSQL程序包,功能顾问良师益友,写个简单的XML报表还是可以的。 其步骤大致分为如下: 创建XML文档。 创建RTF模板。 创建数据源和上传RTF模板。 创建请求并添加到你需要的请求组。 以下具体说明: 创建XML文档,其包括如下部分: 分别是参数、触…

付费文章合集第二期

☞☞付费文章合集第一期 感谢大家一年来的陪伴与支持&#xff01; 对于感兴趣的文章点标题能跳转原文阅读啦~~ 21、Matlab信号处理——基于LSB和DCB音频水印嵌入提取算法 22、CV小目标识别——AITOD数据集&#xff08;已处理&#xff09; 23、Matlab信号发生器——三角波、…

API低代码平台介绍3-异构数据源的数据查询功能

异构数据源的数据查询功能 在上一篇文章中我们通过API平台定义了一个最基本的数据查询接口&#xff0c;本篇文章我们将上升难度&#xff0c;在原有接口的基础上&#xff0c;实现在MySQL数据库和Oracle数据库同时进行数据查询。   什么场景会需要同时对异构数据源进行查询&…