3.1.7.Qt容器大家族(3):QVariant——万能盒子

1.内容介绍

前几节课的容器课,我们讲解了QList、QString和QStringList,它们都有一个共同点:存什么类型,就得声明什么类型。

但是这时候,如果我们需要一个能装任意类型的容器,比如表格里的一行数据,可能包含各种类型的信息,比如int、double、QString等等等等,这时候要怎么办呢?

我们就要邀请我们的老四登场啦!它就是我们今天要讲的——QVariant!

2.讲解QVariant

1.什么是QVariant?

QVariant嘛,简单来说,它是一个万能盒子,什么类型都能往里面装,要装也很容易,直接赋值就行,和普通变量赋值一模一样!

QVariant v1 = 42; //int QVariant v2 = 3.14; //double QVariant v3 = "Hello"; //QString QVariant v4 = QColor(255, 255, 255); //QColor,存储颜色,这个以后会讲

当然,我们也可以用fromValue函数来存储。

QVariant var = QVariant::fromValue(QColor(255, 255, 255));

不管是int、double,还是Qt的类型,甚至是你自己的类型,它都能装进去!

当然,装进去就得取出来,怎么取出来呢?

2.怎么把数据取出来?

装进去很容易,取出来时我们要告诉这个万能盒子“要取出来什么类型”。

很多的常见类型,Qt都帮你写好了转化的函数,像是toInt啊,toDouble啊,toString啊,Qt都搞好了,当然,有些类型Qt没写好,我们就要用模板函数value了,比如QColor啊,QFont什么的。(以后都会讲到)

int a = v1.toInt(); // 取出 int double b = v2.toDouble(); // 取出 double QString c = v3.toString(); // 取出 QString QColor d = v4.value<QColor>(); // 取出 QColor //这里就需要模板函数value了,因为QColor没有专门的方法,Qt总不能把所有的都写一个方法吧

我们这里有一个注意事项,转化的类型不匹配不会报错或者抛出异常,但是可能会返回一个空值。(比如0或空字符串)

看到了吗?QVariant很聪明,会尽量帮你完成类型转化。

那么,QVariant有什么用呢?

3.有什么用?

QVariant最常用的场景就是用在表格控件,一行会有多种数据,类型不同,所以QVariant就是一个很好的选择。

还有信号槽传参、配置文件读写什么的,QVariant都有它的用武之地。

那你可能就会问了,自己的类型能不能传递呢?

4.能不能传递自己的自定义类型?

当然可以!只不过你需要一个小操作,就是注册。你需要用一个叫做Q_DECLARE_METATYPE的宏去注册一下这个类型,如果不注册的话,QVariant就不会认识你这个类型,取出来的时候就会有问题。

#include <QMetaType> //要用这个头文件 struct Student { QString name; int age; }; Q_DECLARE_METATYPE(Student) // 注册 // 装进去 Student s{"小明", 18}; QVariant v = QVariant::fromValue(s); // 取出来 Student s2 = v.value<Student>();

QVariant我们就讲完啦!是不是非常简单呢?对了,你们有没有发现,这几节课我都没有让你们写头文件,这是为什么呢?因为它们根本不用写头文件!为什么不用写头文件呢?因为这些容器的头文件都被Qt的控件给用烂了!绝对会包含它们!就连QObject都会用到!所以我告诉你们,QObject的属性系统传递的就是QVariant!厉害吧?

好啦,这节课就到这里,我们下节课再见,拜拜!