简体   繁体   English

Qt,QVariant,JSON和枚举

[英]Qt, QVariant, JSON and enums

I am trying to figure out how I am supposed to use enumerations in Qt so that I pack them in a QVariant and convert them to a QJsonValue and later JSON. 我试图弄清楚如何在Qt中使用枚举,以便将它们打包在QVariant中并将其转换为QJsonValue和更高版本的JSON。

Following the docs I ended up declaring my enums: 在文档之后,我最终声明了我的枚举:

enum BeautifulColors { Red, Green, Blue };
Q_DECLARE_METATYPE(BeautifulColors);

That way I can use setValue(..) on QVariant to set my custom defined enums as value. 这样,我可以在QVariant上使用setValue(..)将自定义定义的枚举设置为值。

The problem however is QJsonValue::fromVariant() , the docs says: 但是问题是QJsonValue::fromVariant() ,文档说:

Converts variant to a QJsonValue and returns it. 将variant转换为QJsonValue并将其返回。 (...) For all other QVariant types a conversion to a QString will be attempted. (...)对于所有其他QVariant类型,将尝试转换为QString。 If the returned string is empty, a Null QJsonValue will be stored, otherwise a String value using the returned QString. 如果返回的字符串为空,则将存储Null QJsonValue,否则将使用返回的QString来存储String值。

The conversion to QString fails and and my QJsonValue object ends up being Null. 转换为QString失败,并且我的QJsonValue对象最终为Null。

Following the documentation further is confusing: There is a Q_EUM macro for enumeration definition within QObject. 遵循文档进一步令人困惑:QObject中有一个用于枚举定义的Q_EUM宏。 However since QObject is non-copy able I don't think QVariant is supposed to hold it. 但是,由于QObject是不可复制的,所以我不认为QVariant应该拥有它。 There are certainly some hacky was to get it working, but that is not what I am looking for. 当然,要使它正常工作确实有些棘手,但这不是我想要的。 What is the recommended way in Qt to define enums so that they can be used as datatypes and converted into JSON and read from JSON? 在Qt中定义枚举的推荐方法是什么,以便它们可以用作数据类型并转换为JSON并从JSON读取?

Update 更新

Tried the following: 尝试了以下内容:

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();
}

Now it has a typ id and a string representation! 现在,它具有类型ID和字符串表示形式! But not the class holding it: 但不是持有它的班级:

int idRectangle = qMetaTypeId<Rectangle>();

Does not compile and I cannot register it with Q_DECLARE_MEATYPE , because it does not have a constructor. 无法编译,我无法向Q_DECLARE_MEATYPE注册它,因为它没有构造函数。 What if I need QVariants toString() to work with any class? 如果我需要QVariants toString()与任何类一起使用怎么办?

Second Update 第二次更新

Using the Q_GADGET macro I now get a (different) type id for the enum and the class holding it. 现在,使用Q_GADGET宏为枚举和保存它的类获得一个(不同的)类型ID。 However I still only get a string representation for the enum. 但是,我仍然只得到枚举的字符串表示形式。

Q_ENUM or Q_ENUMS are needed to generate the necessary QMetaEnum structure to toString/fromString functionality. 需要Q_ENUMQ_ENUMS来生成toString / fromString功能所需的QMetaEnum结构。

They need to be placed in a QObject derived class with the Q_OBJECT marker or in any class with the Q_GADGET marker in order for moc to process them and generate the necessary code. 必须将它们放置在带有Q_OBJECT标记的QObject派生类中,或者放置在带有Q_GADGET标记的任何类中,以便moc处理它们并生成必要的代码。

The class they are defined in is not the one being stored in the variant though when you store an enum value. 尽管在存储枚举值时,它们定义的类不是存储在变量中的类。 You can consider this class more like a "namespace" for your enum. 您可以将此类视为更像枚举的“命名空间”。

I figured the rest out, to be able to use QVariant::toString() a conversion must be registered for the type held by the QVariant. 我想出了剩下的,为了能够使用QVariant::toString()必须为QVariant持有的类型注册一个转换。

This was added by KDAB in Qt 5.2 ( http://log.cedricbonhomme.org/55/66102.html ) but is nowhere mentioned in the doc QVariant::toString() ! 这是KDAB在Qt 5.2( http://log.cedricbonhomme.org/55/66102.html )中添加的,但是在文档QVariant::toString()没有提及! :( :(

Anyways it also works for plain enums, the following example will output "Apple" 无论如何,它也适用于普通枚举,下面的示例将输出“ Apple”

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();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM