我在头文件中注册了一个枚举类型“ClefType” - 这个枚举使用Q_DECLARE_METATYPE和Q_ENUMS宏在MetaObject系统中注册。 qRegisterMetaType也在类构造函数中调用。
这允许我在Q_PROPERTY中使用此类型,这一切都正常。但是,稍后,我需要能够在给定对象的情况下获得此枚举类型的Q_PROPERTY - 以适合序列化的形式。
理想情况下,存储该枚举成员的整数值会很有用,因为我不希望它特定于所使用的枚举类型 - 最终我希望有几个不同的枚举< /强>
// This is inside a loop over all the properties on a given object
QMetaProperty property = metaObject->property(propertyId);
QString propertyName = propertyMeta.name();
QVariant variantValue = propertyMeta.read(serializeObject);
// If, internally, this QVariant is of type 'ClefType',
// how do I pull out the integer value for this enum?
不幸的是variantValue.toInt();
不起作用 - 自定义枚举似乎不能直接“转换”为整数值。
提前致谢,
亨利
答案 0 :(得分:1)
尝试:
int x = variantValue.value<ClefType>();
答案 1 :(得分:1)
您可以使用QVariant的>>
和<<
运算符来完成此操作。
保存(MyClass *x = new MyClass(this);
和out
为QDataStream
):
const QMetaObject *pObj = x->pObj();
for(int id = pObj->propertyOffset(); id < pObj->propertyCount(); ++id)
{
QMetaProperty pMeta = pObj->property(id);
if(pMeta.isReadable() && pMeta.isWritable() && pMeta.isValid())
{
QVariant variantValue = pMeta.read(x);
out << variantValue;
}
}
装载:
const QMetaObject *pObj = x->pObj();
for(int id = pObj->propertyOffset(); id < pObj->propertyCount(); ++id)
{
QMetaProperty pMeta = pObj->property(id);
if(pMeta.isReadable() && pMeta.isWritable() && pMeta.isValid())
{
QVariant variantValue;
in >> variantValue;
pMeta.write(x, variantValue);
}
}
您需要致电
qRegisterMetaType<CMyClass::ClefType>("ClefType");
qRegisterMetaTypeStreamOperators<int>("ClefType");
除了使用Q_OBJECT
,Q_ENUMS
和Q_PROPERTY
之外。调用qRegisterMetaTypeStreamOperators<int>
告诉Qt使用operator<<
和operator>>
的int版本。
顺便说一下:使用qRegisterMetaType<CMyClass::ClefType>()
而不是名字的形式对我不起作用。如果您使用返回的id来查找名称,可能会更容易。
仅供参考,这是MyClass
定义:
class CMyClass : public QObject
{
Q_OBJECT
Q_ENUMS(ClefType)
Q_PROPERTY(ClefType cleftype READ getCleftype WRITE setCleftype)
public:
CMyClass(QObject *parent) : QObject(parent), m_cleftype(One)
{
qRegisterMetaType<CMyClass::ClefType>("ClefType");
qRegisterMetaTypeStreamOperators<int>("ClefType");
}
enum ClefType { Zero, One, Two, Three };
void setCleftype(ClefType t) { m_cleftype = t; }
ClefType getCleftype() const { return m_cleftype; }
private:
ClefType m_cleftype;
};
Q_DECLARE_METATYPE(CMyClass::ClefType)
答案 2 :(得分:1)
我遇到了同样的问题,并提出了以下解决方案,适用于任何枚举类型:
int x = property.enumerator().value(*reinterpret_cast<const int *>(variantValue.constData()));
答案 3 :(得分:1)
您可以使用新的Q_ENUM宏(Qt 5.5中已添加),而不必担心调用qRegisterMetaType()
。我写了一个测试应用程序(使用Google测试)向我证明它有效:
#include <gtest/gtest.h>
#pragma warning(push, 0)
#include <QObject>
#include <QtTest/QSignalSpy>
#pragma warning(pop)
class tColoredObject : public QObject
{
Q_OBJECT
public:
enum class eColor
{
Red = 1,
Blue = 2,
Green = 3
};
Q_ENUM(eColor)
tColoredObject() : m_color(eColor::Red) {}
void SendSignal(tColoredObject::eColor color) { emit TestSignal(color); }
signals:
void TestSignal(tColoredObject::eColor color);
private:
eColor m_color;
};
TEST(Enum, EnumValue)
{
const QVariant varRed = QVariant::fromValue(tColoredObject::eColor::Red);
const QVariant varBlue = QVariant::fromValue(tColoredObject::eColor::Blue);
const QVariant varGreen = QVariant::fromValue(tColoredObject::eColor::Green);
EXPECT_EQ(varRed.toUInt(), static_cast<uint>(tColoredObject::eColor::Red));
EXPECT_EQ(varBlue.toUInt(), static_cast<uint>(tColoredObject::eColor::Blue));
EXPECT_EQ(varGreen.toUInt(), static_cast<uint>(tColoredObject::eColor::Green));
EXPECT_TRUE(varRed.canConvert<tColoredObject::eColor>());
EXPECT_TRUE(varBlue.canConvert<tColoredObject::eColor>());
EXPECT_TRUE(varGreen.canConvert<tColoredObject::eColor>());
EXPECT_EQ(varRed.value<tColoredObject::eColor>(), tColoredObject::eColor::Red);
EXPECT_EQ(varBlue.value<tColoredObject::eColor>(), tColoredObject::eColor::Blue);
EXPECT_EQ(varGreen.value<tColoredObject::eColor>(), tColoredObject::eColor::Green);
}
TEST(Enum, EmitFunctionSucceeds)
{
tColoredObject objColor;
QSignalSpy OnTestSignal(&objColor, &tColoredObject::TestSignal);
objColor.TestSignal(tColoredObject::eColor::Blue);
EXPECT_EQ(1, OnTestSignal.count());
QList<QVariant> arguments = OnTestSignal.takeFirst();
EXPECT_EQ(tColoredObject::eColor::Blue, arguments.at(0).value<tColoredObject::eColor>());
}
答案 4 :(得分:0)
我的非花哨解决方案是对 int
进行类型转换。我不知道它是否因为新的编译器而有效(原始问题有十多年了),但是在使用 QSettings 设置值时它有效:
enum iconSep_e {
sepNone,
sepSpace,
sepTab,
};
在函数内部...
QSettings settings;
settings.setValue(QStringLiteral("iconSep"), sepTab);
检索时,我直接打开 int
,但使用 enum
作为大小写值:
QVariant var = settings.value(QStringLiteral("iconSep"));
if (!var.isNull()) {
int iconSep = var.toInt();
switch (iconSep) {
case sepNone:
ui->radioIconSepNone->setChecked(true);
break;
case sepSpace:
ui->radioIconSepSpace->setChecked(true);
break;
case sepTab:
ui->radioIconSepTab->setChecked(true);
break;
}
}
我做了一些测试,类型转换也有效:
enum iconSep_e iconSep = static_cast<enum iconSep_e>(var.toInt());