Qt, QVariant, JSON and enums
Qt, QVariant, JSON and enums
我试图弄清楚我应该如何在Qt中使用枚举,以便我将它们打包在QVariant中并将它们转换为QJsonValue和后来的JSON。
根据文档,我最终声明了我的枚举:
enum BeautifulColors { Red, Green, Blue };
Q_DECLARE_METATYPE(BeautifulColors);
这样我就可以在QVariant
上使用setValue(..)
来设置我自定义的枚举值。
问题是QJsonValue::fromVariant()
,文档说:
将变量转换为QJsonValue并返回它。(...)对于所有其他QVariant类型,将转换为QString尝试。如果返回的字符串为空,QJsonValue将为Null
转换到QString
失败,并且我的QJsonValue
对象最终为Null。
接下来的文档是令人困惑的:在QObject中有一个Q_EUM
宏用于枚举定义。然而,由于QObject是不可复制的,我不认为QVariant应该持有它。当然有一些hack是让它工作,但这不是我想要的。在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。但是,我仍然只得到enum的字符串表示形式。
需要Q_ENUM
或Q_ENUMS
来生成toString/fromString功能所需的QMetaEnum
结构。
为了让moc
处理它们并生成必要的代码,它们需要被放置在带有Q_OBJECT
标记的QObject
派生类中或任何带有Q_GADGET
标记的类中。
当存储枚举值时,定义它们的类并不是存储在变体中的类。您可以将该类看作是enum的"命名空间"。
我把剩下的弄清楚了,为了能够使用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();
}
- C++核心准则 C35 对于接口类"A base class destructor should be either public and virtual, or protected and nonv
- 为什么C++逐位AND运算符在不同大小的操作数中表现为这样
- 为什么 Clang 不允许"and"作为函数名称?
- 位阵列上的快速AND运算
- 是否可以在 C++03 中定义'move-and-swap idiom'等效项
- BoostPython and CMake
- OpenSSL BIO and SSL_read
- Gurobi GRBModel and GRBmodel in C++
- std::visit and std::variant usage
- SHBrowseForFolder with BIF_BROWSEFORCOMPUTER and SHGetPathFr
- Directx12 and keystrokes
- different between int **arr =new int [ n]; and int a[i][j]?
- C++ getenv and setenv
- Inference pytorch C++ with alexnet and cv::imread image
- Visual Studio 2019 C++ and std::filesystem
- 保证逻辑 AND 表达式中的函数调用
- python ctypes and C++ pointers
- C++ const char with .begin() and .end()
- Threads with Classes and std::packaged_task
- Qt, QVariant, JSON and enums