2016-09-26 2 views
2

Я пытаюсь выяснить, как я должен использовать перечисления в Qt, чтобы упаковать их в QVariant и преобразовать их в QJsonValue и позже JSON.Qt, QVariant, JSON и перечисления

После Документов я заканчивал объявляя мои перечисления:

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

Таким образом, я могу использовать setValue(..) на QVariant установить мой заказ определенных перечисления в качестве значения.

Проблема, однако, QJsonValue::fromVariant(), то документы говорит:

Преобразует вариант в QJsonValue и возвращает его. (...) Для всех других типов QVariant преобразование в QString будет выполнено в . Если возвращаемая строка пуста, значение Null QJsonValue будет сохранено в , в противном случае - значение String с использованием возвращаемого QString.

Преобразование в QString терпит неудачу, и и мой QJsonValue объект заканчивает тем, что Null.

Последующая документация еще более запутанна: для определения перечисления в QObject существует макрос Q_EUM. Однако, поскольку QObject не копируется, я не думаю, что QVariant должен его удерживать. Конечно, некоторые хакки должны были заставить его работать, но это не то, что я ищу. Каким образом рекомендуется использовать Qt для определения перечислений, чтобы их можно было использовать в качестве типов данных и преобразовать в JSON и читать из JSON?

Update

Пробовал следующее:

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

Теперь он имеет тип идентификатор и строковое представление! Но не класс его проведение:

int idRectangle = qMetaTypeId<Rectangle>(); 

не компилируется, и я не могу зарегистрировать его Q_DECLARE_MEATYPE, потому что он не имеет конструктора. Что делать, если мне нужно QVariants toString() для работы с любым классом?

Второе обновление

Использование Q_GADGET макроса Теперь я получаю (разные) идентификатор типа для перечисления и класс его проведения. Однако я все еще получаю только строковое представление для перечисления.

ответ

2

Q_ENUM или Q_ENUMS необходимы для создания необходимой структуры QMetaEnum функции toString/fromString.

Они должны быть помещены в QObject производного класса с Q_OBJECT маркером или в любом классе с Q_GADGET маркером для того, чтобы moc обрабатывать их и генерировать необходимый код.

Класс, в котором они определены, не является тем, который хранится в варианте, хотя при сохранении значения перечисления. Вы можете считать этот класс более похожим на «пространство имен» для вашего перечисления.

+0

Thx за быстрый ответ! – Nils

1

Я понял, что остальное, чтобы иметь возможность использовать 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(); 
} 
+0

Вы можете проверить, есть ли сообщение об ошибке в отношении документации по Qt об этом отсутствующий? –

+1

Пришлось его создать: https://bugreports.qt.io/browse/QTBUG-56204 – Nils

+1

Я бы предложил сообщить об этом вместо компонента «Документация». –

Смежные вопросы