【问题标题】:Qt, QVariant, JSON and enumsQt、QVariant、JSON 和枚举
【发布时间】:2016-09-26 15:42:58
【问题描述】:

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

按照文档,我最终声明了我的枚举:

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

这样我可以在QVariant 上使用setValue(..) 将我的自定义枚举设置为值。

但问题是 QJsonValue::fromVariant(),文档说:

将变体转换为 QJsonValue 并返回它。 (...) 对于所有其他 QVariant 类型,转换为 QString 将是 尝试过。如果返回的字符串为空,则为 Null 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();
}

现在它有一个 typ id 和一个字符串表示!但不是持有它的班级:

int idRectangle = qMetaTypeId<Rectangle>();

无法编译,我无法使用Q_DECLARE_MEATYPE 注册它,因为它没有构造函数。如果我需要 QVariants toString() 来处理任何类怎么办?

第二次更新

使用 Q_GADGET 宏,我现在为枚举和持有它的类获得了一个(不同的)类型 ID。但是我仍然只得到枚举的字符串表示形式。

【问题讨论】:

    标签: c++ json qt enums


    【解决方案1】:

    需要Q_ENUMQ_ENUMS 才能为toString/fromString 功能生成必要的QMetaEnum 结构。

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

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

    【讨论】:

    • 感谢您的快速回答!
    【解决方案2】:

    我想通了,为了能够使用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 的文档中是否有关于这个缺失的错误报告吗?
    • 我建议改为针对组件“文档”进行报告。
    猜你喜欢
    • 2014-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多