关于QVariant的说明

来源:互联网 发布:银河历险记3 知乎 编辑:程序博客网 时间:2024/05/09 05:46

在有些情况下,我们希望把数据存储在一个变量中。例如,我有一个数组,既希望存整数,又希望存浮点数,还希望存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使用操作符对数据 进行操作,例如

  1. qRegisterMetaTypeStreamOperators<BusinessCard>(“BusinessCard”);
原创粉丝点击