Qt、QVariant、JSON和枚举

3

我正在尝试弄清楚如何在Qt中使用枚举,以便将它们打包到QVariant中,并将它们转换为QJsonValue和后续的JSON。

按照文档的指示,我声明了我的枚举:

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

这样我可以使用setValue(..)QVariant上设置自定义枚举作为值。
然而问题出现在QJsonValue::fromVariant()上,文档说:

将变体转换为QJsonValue并返回。(...) 对于所有其他QVariant类型,将尝试转换为QString。 如果返回的字符串为空,则存储Null QJsonValue,否则使用返回的QString存储String值。

转换为QString失败,我的QJsonValue对象最终为空。
根据文档进一步了解会让人感到困惑:在QObject中有一个用于枚举定义的Q_ENUM宏。但是,因为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进行注册,因为它没有构造函数。如果我需要QVariant的toString()与任何类一起工作怎么办?

第二次更新

使用Q_GADGET宏,现在我可以得到枚举和持有它的类的另一个类型ID。但是,我仍然只能获得枚举的字符串表示。

2个回答

4

Q_ENUMQ_ENUMS是为了生成必要的QMetaEnum结构以进行toString/fromString功能而需要的。

它们需要放置在继承自QObject类且带有Q_OBJECT标记的类中,或者放置在带有Q_GADGET标记的任何类中,以便moc处理它们并生成必要的代码。

当您存储枚举值时,它们定义的类不是存储在变量中的那个类。 您可以将这个类视为您的枚举的“命名空间”。


谢谢您的快速回答! - Nils

3
我已经理解了其余的部分,为了能够使用 QVariant::toString(),必须为 QVariant 持有的类型注册一个转换。这是由 KDAB 在 Qt 5.2 中添加的 (http://log.cedricbonhomme.org/55/66102.html),但在文档 QVariant::toString() 中没有提到! :(
无论如何,它也适用于普通的枚举类型,以下示例将输出 "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();
}

你能否检查一下在Qt的文档中是否有关于这个缺失的错误报告? - Kevin Krammer
1
我建议您将其报告给“文档”组件。 - Kevin Krammer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接