【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 intint x = v.toInt();              // x = 123out << v;                       // Writes a type tag and an int to outv = QVariant("hello");          // The variant now contains a QByteArrayv = QVariant(tr("hello"));      // The variant now contains a QStringint y = v.toInt();              // y = 0 since v cannot be converted to an intQString 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 variantint z = v.toInt();              // z = 123qDebug("Type is %s",            // prints "Type is int"v.typeName());v = v.toInt() + 100;            // The variant now hold the value 223v = 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);// 创建包含节点信息的 QListWidgetItemQListWidgetItem *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
在这里插入图片描述

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

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

相关文章

二、jacoco代码覆盖率工具

jacoco代码覆盖率工具 一、jacoco介绍二、常见的java代码覆盖率工具三、为什么选择jacoco四、jacoco的特点五、Jacoco 支持的覆盖率指标六、那些暂未支持的覆盖率指标七、jacoco技术原理八、Jacoco 下载与配置九、jacoco主要文件十、jacoco使用流程十一、jacoco单元测试实战1、…

程序人生 | 人生如棋,落子无悔

人生的开始&#xff0c;始于哭声&#xff0c;浮浮沉沉几十年。终了&#xff0c;一声长叹&#xff0c;在一片哭声中撒手离去。 人生的道路虽然漫长&#xff0c;但是关键就是那么几次机会的选择&#xff0c;可以决定此后几十年的光阴。 有个故事讲&#xff1a;古代有个人去砍柴…

Python 将Excel转换为多种图片格式(PNG, JPG, BMP, SVG)

目录 安装Python Excel库 使用Python将Excel工作表转换为PNG&#xff0c;JPG或BMP图片 使用Python将Excel特定单元格区域转换为PNG&#xff0c;JPG或BMP图片 使用Python将Excel工作表转换为SVG图片 有时&#xff0c;你可能希望以图片形式分享Excel数据&#xff0c;以防止他…

c++ cpp 在类中执行线程 进行恒定计算

在编程中&#xff0c;顺序执行是常见的模式&#xff0c;但是对cpu的利用率不是很高&#xff0c;采用线程池&#xff0c;又太麻烦了&#xff0c;原因是还得不断地把任务拆分&#xff0c;扫描返回值。 如果 初始化n个类的时候&#xff0c;传递数据自身即可异步计算&#xff0c;那…

《Python编程从入门到实践》day25

# 昨日知识点回顾 如何创建多行外星人 碰撞结束游戏 创建game_stats.py跟踪统计信息 # 今日知识点学习 第14章 记分 14.1 添加Play按钮 14.1.1 创建Button类 import pygame.font# button.py class Button:def __init__(self, ai_game, msg):"""初始化按钮…

在Leaflet中点对象使用SVG和Canvas两种模式的对比

目录 前言 一、关于SVG和Canvas 1、SVG知识 2、Canvas知识 3、优缺点 二、SVG和Canvas在Leaflet的使用 1、相关类图 2、Leaflet的默认展示方式 三、SVG和Canvas实例及性能对比 1、SVG模式及性能对比 2、Canvas优化 总结 前言 众所周知&#xff0c;在Leaflet当中&#…

实现桌面动态壁纸——认识 WebView2 控件

目录 前言 一、什么是 WebView2 &#xff1f; 二、使用示例存储库 2.1 下载存储库 2.2 编译解决方案项目文件 2.3 运行示例程序 三、如何修改 WebView2 示例 本文来源于&#xff1a;https://blog.csdn.net/qq_59075481/article/details/138637909。 前言 上一节我们讲…

ASP.NET学生信息管理系统

摘 要 本文介绍了在ASP.net环境下采用“自上而下地总体规划&#xff0c;自下而上地应用开发”的策略开发一个管理信息系统的过程。通过分析某一学校学生管理的不足&#xff0c;创建了一套行之有效的计算机管理学生的方案。文章介绍了学生管理信息系统的系统分析部分&#xff0c…

聚合工程搭建、工程依赖导入

上一章讲了自动化云测平台的一些环境的准备 如果还未完成云服务器的环境搭建和本地环境的搭建&#xff0c;请点击左侧 -> 传送门 那么正式开始这一章的内容 聚合工程搭建 创建项目 我们先给项目命个名&#xff1a;xxx-meter&#xff0c;构建系统&#xff0c;我们选择M…

HBuilder报错--openssl-legacy-provider is not allowed in NODE_OPTIONS解决方法

目录 一、问题描述二、解决方法 一、问题描述 HBuilder编译时报错&#xff1a;–openssl-legacy-provider is not allowed in NODE_OPTIONS 二、解决方法 将 windows 环境变量 NODE_OPTIONS 的值设置为空&#xff0c;由&#xff1a; 改为&#xff1a;

Zabbix监控中文乱码问题解决方法

一、问题描述 1.查看Zabbix仪表盘 在Zabbix的监控仪表盘界面&#xff0c;字体显示为“方框”&#xff0c;无法查看到具体的性能指标名称。 2.问题分析 Zabbix的web端没有中文字库&#xff0c;导致切换到中文页面&#xff0c;中文成了乱码这个问题&#xff0c;我们最需要把中文…

暗区突围pc资格 暗区突围pc端测试资格获取

《暗区突围》的诞生&#xff0c;仿佛在游戏界投下了一枚深水炸弹&#xff0c;它不仅仅是射击游戏的新标杆&#xff0c;更是对玩家策略思维、生存直觉与团队协作能力的一次全面考验。在这个精心构建的虚拟战场中&#xff0c;每一次踏入暗区&#xff0c;都是对未知的探索&#xf…