转载: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. QMap<QString, QVariant> fruitMap;
  5. fruitMap["Orange"] = 2.10;
  6. fruitMap["Pineapple"] = 3.85;
  7. 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. // ...
  7. }

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

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

qRegisterMetaTypeStreamOperators<BusinessCard>("BusinessCard");

  1. 本文出自 “豆子空间” 博客,http://devbean.blog.51cto.com/448512/276235
时间: 2024-10-15 19:26:26

转载:QByteArray和QVariant的相关文章

QVariant实质

QVariant实质 QVariant是一种可以存储不同类型的数据结构,在很多场合这是很有用得为了达到这种目的,可以想象,该对象应该存储对象的类型信息,数据信息以及其他辅助详细考虑用途,这种对象必须支持对不同对象的存储,对存储类型的检测以及取对象三个功能1.对象的存储代码见下:QVariant(Type type);    QVariant(int typeOrUserType, const void *copy);    QVariant(int typeOrUserType, const v

【Qt编程】基于Qt的词典开发系列&amp;lt;九&amp;gt;--JSON数据解析

在上一篇文章<用户登录及API调用的实现>中,我通过程序实现了用户登录及API调用的实现.从而能够实现网络查词.添词的操作.可是.从上文中能够看到.调用API后返回的是JSON格式的数据,例如以下图所看到的(在QtCreator中的显示): 为了更好的观察JSON格式.我整理后显演示样例如以下: 显然.为了显示查词的结果,我们必须在上图中提取实用的信息,并正确的显示出来. 上图中每一行内容的意思我已经在文章<调用网络API>中作了解释.我在词典中选择想要显示的内容有:单词本身.单词

QT QString 很全的使用 (转)

QString, QByteArray, 和 QVariant这三个类和容器有许多相同之处,并且在一些情况下可以被当作特殊的容器. 同样,像容器,这些类使用隐式共享来优化内存和速度. 我们将从QString开始. 字符串被每个GUI程序所使用,不仅是用户界面而且还有数据结构. C++原生提供两种字符串: 传统的C风格以'\0'结尾的字符数组和std::string类. 与这些不同,QString使用16-bit Unicode值. Unicode 包含 ASCII 和 Latin-1 这个子集和

(转)STL

C++容器类 C++中的容器类包括“顺序存储结构”和“关联存储结构”,前者包括vector,list,deque等:后者包括set,map,multiset,multimap等. 若需要存储的元素数在编译器间就可以确定,可以使用数组来存储,否则,就需要用到容器类了. 1.vector 连续存储结构,每个元素是在内存上是连续的: 支持高效的随机访问和在尾端插入/删除操作,但其他位置的插入/删除操作效率低下: 2.deque 连续存储结构,即其每个元素在内存上也是连续的,类似于vector,不同之处

【Qt编程】基于Qt的词典开发系列&lt;九&gt;--JSON数据解析

在上一篇文章<用户登录及API调用的实现>中,我通过程序实现了用户登录及API调用的实现,从而能够实现网络查词.添词的操作.但是,从上文中可以看到,调用API后返回的是JSON格式的数据,如下图所示(在QtCreator中的显示): 为了更好的观察JSON格式,我整理后显示如下: 显然,为了显示查词的结果,我们必须在上图中提取有用的信息,并正确的显示出来.上图中每一行内容的意思我已经在文章<调用网络API>中作了解释.我在词典中选择想要显示的内容有:单词本身.单词ID.中文解释.英

QT中的字符串处理函数

Fn 1 : arg 这个函数的具体声明不写了,它有20个重载,典型的示例代码如下: 1: #include <QtCore/QCoreApplication> 2: #include <iostream> 3: #include <stdio.h> 4: using namespace std; 5: 6: int main() 7: { 8: QString str = QString("Ggicci is %1 years old, and majors

QVaraint类

一.QVaraint简介     QVaraint类作为一个包含了大多数Qt普通类型的的联合体类.因为c++联合体没有构造函数和析构函数的,许多继承的Qt类不能够在联合体当中使用.(联合体当中的变量共用一个存储区),没有了联合变量,我们在物体属性以及数据库的工作等方面受到很多的困扰.一个QVariant对象一段时间只保留一种类型的值.我们可以使用 bool QVariant::canConvert(int targetTypeId) const来判断该类型是否可以转换. 二.使用 QDataSt

【转载】Qt中的QString,QByteArray,Qchar, char*

先要说的是QString. 之所以把QString单独拿出来,是因为string是很常用的一个数据结构,甚至在很多语言中,比如JavaScript,都是把string作为一种同int等一样的基本数据结构来实现的. 每一个GUI程序都需要string,这些string可以用在界面上的提示语,也可以用作一般的数据结构.C++语言提供了两种字符串的实现:C风格的 字符串,以'\0‘结尾:std::string,即标准模版库中的类.Qt则提供了自己的字符串实现:QString.QString以16位 U

QT:QString、QByteArray和char *的转换 【转载】

原文网址:http://blog.csdn.net/light1028/article/details/7899541 第一种,数据流的方式,这里只说从QByteArray转向QString. QByteArray encodedString = "xxx"; QTextCodec *codec = QTextCodec::codecForName("KOI8-R"); QString string = codec->toUnicode(encodedStri