开发者社区> 科技小能手> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

Qt学习之路(51): QByteArray和QVariant

简介:
+关注继续查看

前面我们在介绍QString的最后部分曾经提到了QByteArray这个类。现在我们就首先对这个类进行介绍。

QByteArray具有类似与QString的API。它也有相应的函数,比如left(), right(), mid()等。这些函数不仅名字和QString一样,而且也具有几乎相同的功能。QByteArray可以存储原生的二进制数据和8位编码的文本数据。这句话怎么理解呢?我们知道,计算机内部所有的数据都是以0和1的形式存储的。这种形式就是二进制。比如一串0、1代码:1000,计算机并不知道它代表的是什么,这需要由上下文决定:它可以是整数8,也可以是一个ARGB的颜色(准确的说,整数8的编码并不是这么简单,但我们姑且这个理解吧)。对于文件,即便是一个文本文件,读出时也可以按照二进制的形式读出,这就是二进制格式。如果把这些二进制的0、1串按照编码解释成一个个字符,就是文本形式了。因此,QByteArray实际上是原生的二进制,但是也可以当作是文本,因此拥有文本的一些操作。但是,我们还是建议使用QString表示文本,重要的原因是,QString支持Unicode。

为了方便期间,QByteArray自动的保证“最后一个字节之后的那个位”是'\0'。这就使得QByteArray可以很容易的转换成const char *,也就是上一章节中我们提到的那两个函数。同样,作为原生二进制存储,QByteArray中间也可以存储'\0',而不必须是'\0'在最后一位。

在有些情况下,我们希望把数据存储在一个变量中。例如,我有一个数组,既希望存整数,又希望存浮点数,还希望存string。对于Java来说,很简单,只要把这个数组声明成Object[]类型的。这是什么意思呢?实际上,这里用到的是继承。在Java中,int和float虽然是原生数据类型,但是它们都有分别对应一个包装类Integer和Float。所有这些Integer、Float和String都是继承于Object,也就是说,Integer、Float和String都是一个(也就是is-a的关系)Object,这样,Object的数组就可以存储不同的类型。但是,C++中没有这样一个Object类,原因在于,Java是单根的,而C++不是。在Java中,所有类都可以上溯到Object类,但是C++中没有这么一个根。那么,怎么实现这么的操作呢?一种办法是,我们都存成string类,比如int i=10,我就存"10"字符串。简单的数据类型固然可以,可复杂一些的呢?比如一个颜色?难道要把ARGB所有的值都转化成string?这种做法很复杂,而且失去了C++的类型检查等好处。于是我们想另外的办法:创建一个Object类,这是一个“很大很大的”类,里面存储了几乎所有的数据类型,比如下面的代码:


  1. class Object  
  2. {  
  3. public:  
  4.     int intValue;  
  5.     float floatValue;  
  6.     string stringValue;  
  7. }; 

这个类怎么样?它就足以存储int、float和string了。嗯,这就是我们的思路,也是Qt的思路。在Qt中,这样的类就是QVariant

QVariant可以保存很多Qt的数据类型,包括QBrush、QColor、QCursor、QDateTime、QFont、QKeySequence、QPalette、QPen、QPixmap、QPoint、QRect、QRegion、QSize和QString,并且还有C++基本类型,如int、float等。QVariant还能保存很多集合类型,如QMap<QString, QVariant>, QStringList和QList<QVariant>。item view classes,数据库模块和QSettings都大量使用了QVariant类,,以方便我们读写数据。

QVariant也可以进行嵌套存储,例如


  1. QMap<QString, QVariant> pearMap;  
  2. pearMap["Standard"] = 1.95;  
  3. pearMap["Organic"] = 2.25;  
  4.  
  5. QMap<QString, QVariant> fruitMap;  
  6. fruitMap["Orange"] = 2.10;  
  7. fruitMap["Pineapple"] = 3.85;  
  8. fruitMap["Pear"] = pearMap; 

QVariant被用于构建Qt Meta-Object,因此是QtCore的一部分。当然,我们也可以在GUI模块中使用,例如


  1. QIcon icon("open.png");  
  2. QVariant variant = icon;  
  3. // other function  
  4. QIcon icon = variant.value<QIcon>(); 

我们使用了value<T>()模版函数,获取存储在QVariant中的数据。这种函数在非GUI数据中同样适用,但是,在非GUI模块中,我们通常使用toInt()这样的一系列to...()函数,如toString()等。

如果你觉得QVariant提供的存储数据类型太少,也可以自定义QVariant的存储类型。被QVariant存储的数据类型需要有一个默认的构造函数和一个拷贝构造函数。为了实现这个功能,首先必须使用Q_DECLARE_METATYPE()宏。通常会将这个宏放在类的声明所在头文件的下面:


  1. Q_DECLARE_METATYPE(BusinessCard) 

然后我们就可以使用:


  1. BusinessCard businessCard;  
  2. QVariant variant = QVariant::fromValue(businessCard);  
  3. // ...  
  4. if (variant.canConvert<BusinessCard>()) {  
  5.     BusinessCard card = variant.value<BusinessCard>();  
  6.     // ...  

由于VC 6的编译器限制,这些模板函数不能使用,如果你使用这个编译器,需要使用qVariantFromValue(), qVariantValue<T>()和qVariantCanConvert<T>()这三个宏。

如果自定义数据类型重写了<<和>>运算符,那么就可以直接在QDataStream中使用。不过首先需要使用qRegisterMetaTypeStreamOperators<T>().宏进行注册。这就能够让QSettings使用操作符对数据进行操作,例如


  1. qRegisterMetaTypeStreamOperators<BusinessCard>("BusinessCard"); 

本文转自 FinderCheng 51CTO博客,原文链接: http://blog.51cto.com/devbean/276235

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
为何一个@LoadBalanced注解就让RestTemplate拥有负载均衡的能力?【享学Spring Cloud】(中)
为何一个@LoadBalanced注解就让RestTemplate拥有负载均衡的能力?【享学Spring Cloud】(中)
21 0
Inside Spring - learning notes - Jerry Wang的Spring学习笔记
Inside Spring - learning notes - Jerry Wang的Spring学习笔记
33 0
分享一个学习Git的网站 Learn Git Branching
分享一个学习Git命令的网站,循序渐进按课程闯关编写的,做的非常棒,界面还很可爱! 建议手动输入git命令,可以在动画中很明白地看到指针和路径是如何变化的,很有趣。
995 0
Nancy之Pipelines三兄弟(Before After OnError)
原文:Nancy之Pipelines三兄弟(Before After OnError) 一、简单描述 Before:如果返回null,拦截器将主动权转给路由;如果返回Response对象,则路由不起作用。
748 0
ArrayList对象排序
前言:最近对收音机的开发,遇到一个需求,将收藏列表显示在前,电台列表显示在后,所以需要对列表进行对象排序,在此做一个总结. 步骤1 创建比较器,指定排序规则 导入此包 java.
658 0
JS-Array数组对象
Array对象练习 实验 concat() var myArray = [1, 2, 3, 4, 5]; var arr = myArray.concat('上山打老虎'); document.
732 0
Spring.Net Aop 学习
浅析Spring.net 中的Aop使用 Spring.NET 中的 AOP .NET中AOP的几种实现方案 Spring.NET学习笔记12——面向切面编程(基础篇) Level 300
544 0
近期的安全视频,学习资料
http://www.nosuchcon.org/streaming/video/ https://www.
514 0
STL之vector,数组线性容器array,list容器,算法find,find_if,bind1st,仿函数
 1.STL(Standard Template Library,是用泛型技术来设计完成的实例)的概念与组成 Iterator(迭代器) Container(容器) Algorithm(算法) Adaptors(配接器)   STL的六大组件分别是: 容器(Container) 算法(Algorithm) 迭代器(Iterat
1056 0
23704
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载