我试图弄清楚我应该如何在Qt中使用枚举,以便将它们打包在QVariant中并将它们转换为QJsonValue以及后来的JSON。
根据文档,我最终宣布了我的枚举:
enum BeautifulColors { Red, Green, Blue };
Q_DECLARE_METATYPE(BeautifulColors);
这样我就可以setValue(..)
使用QVariant
将我自定义的枚举设置为值。
问题是QJsonValue::fromVariant()
,文档说:
将变体转换为QJsonValue并返回它。 (......) 对于所有其他QVariant类型,将转换为QString 尝试。如果返回的字符串为空,则为空QJsonValue 存储,否则使用返回的QString的String值。
转换为QString
失败,而我的QJsonValue
对象最终为空。
在文档之后进一步令人困惑:QObject中的枚举定义有一个Q_EUM
宏。但是,由于QObject是不可复制的,我不认为QVariant应该持有它。肯定有一些hacky是让它工作,但这不是我想要的。 Qt中定义枚举的推荐方法是什么,以便它们可以用作数据类型并转换为JSON并从JSON读取?
更新
尝试以下方法:
rectangle.h
#ifndef RECTANGLE_H
#define RECTANGLE_H
#include <QObject>
class Rectangle : public QObject
{
Q_OBJECT
public:
enum Color
{
Red,
Green,
Blue,
};
Q_ENUM(Color)
Rectangle(double x, double y, Color color, QObject *parent = 0);
private:
double _x;
double _y;
Color _color;
};
#endif
rectangle.cpp
#include "rectangle.h"
Rectangle::Rectangle(double x, double y, Rectangle::Color color, QObject *parent)
: QObject(parent)
, _x(x)
, _y(y)
, _color(color)
{
}
main.cpp
#include <QVariant>
#include <QDebug>
#include <QString>
#include "rectangle.h"
int main(int argc, char *argv[])
{
int id = qMetaTypeId<Rectangle::Color>();
Rectangle::Color blueColor = Rectangle::Blue;
QVariant myVariant;
myVariant.setValue(blueColor);
qDebug() << id;
qDebug() << myVariant.toString();
}
现在它有一个典型ID和一个字符串表示!但不是持有它的班级:
int idRectangle = qMetaTypeId<Rectangle>();
不编译,我无法在Q_DECLARE_MEATYPE
注册,因为它没有构造函数。如果我需要QVariants toString()来处理任何类,该怎么办?
第二次更新
使用Q_GADGET宏我现在为枚举和持有它的类获得(不同的)类型id。但是我仍然只获得枚举的字符串表示。
答案 0 :(得分:3)
Q_ENUM
或Q_ENUMS
需要为toString / fromString功能生成必要的QMetaEnum
结构。
他们需要使用QObject
标记放置在Q_OBJECT
派生类中,或者放在带有Q_GADGET
标记的任何类中,以便moc
处理它们并生成必要的代码。
虽然存储枚举值时,它们所定义的类不是存储在变体中的类。 你可以认为这个类更像是一个&#34;命名空间&#34;为你的枚举。
答案 1 :(得分:1)
我认为剩下的就是,为了能够使用QVariant::toString()
,必须为QVariant持有的类型注册转换。
这是由KDAB在Qt 5.2(http://log.cedricbonhomme.org/55/66102.html)中添加的,但在文档QVariant::toString()
中没有提及! :(
无论如何它也适用于普通枚举,以下示例将输出&#34; Apple&#34;
enum Fruit {
Apple,
Pear,
Orange
};
Q_DECLARE_METATYPE(Fruit)
QString Fruit2QString(Fruit fruit)
{
switch(fruit)
{
case Apple:
return "Apple";
case Pear:
return "Pear";
case Orange:
return "Orange";
}
return "asdf";
}
int main(int argc, char *argv[])
{
std::function<QString(Fruit)> f = &Fruit2QString;
bool success = QMetaType::registerConverter<Fruit, QString>(f);
Q_ASSERT(success);
QVariant v;
v.setValue(Fruit::Apple);
qDebug() << v.toString();
}