如何解决枚举属性不被认可
我一直在尝试实现一些我认为应该非常简单的东西,但我遇到了问题。简而言之,我有一个包含一些 Q_Properties
的类,其中一些我想成为命名空间级别的 enum
值。我的问题是,如果我将 enum
及其 namespace
移动到单独的文件中,QProperty
系统无法识别该属性是 enum
值。
这是一个精简版的说明:
一个文件包含一个带有枚举的命名空间以及我试图与枚举一起使用的类:
#ifndef ENUMPROPERTYTEST_H
#define ENUMPROPERTYTEST_H
#include <QObject>
#include "enumTest.h" //contains the other namespace and enum I want to use
namespace Test_SameFile {
Q_NAMESPACE
enum NSEnum_SameFile {
A1,A2,A3
};
Q_ENUM_NS(NSEnum_SameFile)
}
class EnumPropertyTest : public QObject
{
Q_OBJECT
Q_PROPERTY(int INT1 MEMBER myInt)
//this enum is declared in the same file and works as expected
Q_PROPERTY(Test_SameFile::NSEnum_SameFile ENUMVAL1 MEMBER a)
//this enum is declared in a separate header file and does not
Q_PROPERTY(Test_DiffFile::NSEnum_DiffFile ENUMVAL2 MEMBER g)
public:
explicit EnumPropertytest() : QObject() {}
~EnumPropertytest() {}
private:
int myInt = 5;
Test_SameFile::NSEnum_SameFile a = Test_SameFile::A2;
Test_DiffFile::NSEnum_DiffFile g = Test_DiffFile::T2;
};
#endif // ENUMPROPERTYTEST_H
#ifndef ENUMTEST_H
#define ENUMTEST_H
#include <QObject>
namespace Test_DiffFile {
Q_NAMESPACE
enum NSEnum_DiffFile {
T1,T2,T3
};
Q_ENUM_NS(NSEnum_DiffFile)
}
#endif // ENUMTEST_H
我的主要内容:
#include <QObject>
#include <QMetaProperty>
#include <QDebug>
#include "enumpropertytest.h"
int main()
{
auto id1 = qRegisterMetaType<Test_SameFile::NSEnum_SameFile>();
auto id2 = qRegisterMetaType<Test_DiffFile::NSEnum_DiffFile>();
auto e1 = QMetaEnum::fromType<Test_SameFile::NSEnum_SameFile>();
qDebug() << "e1 id: " << id1 << ",valid:" << e1.isValid() << ",scope : " << e1.scope();
auto e2 = QMetaEnum::fromType<Test_DiffFile::NSEnum_DiffFile>();
qDebug() << "e2 id: " << id2 << ",valid:" << e2.isValid() << ",scope : " << e2.scope();
EnumPropertyTest t;
auto mo = t.MetaObject();
for (int i = mo->propertyOffset(); i < mo->propertyCount(); ++i){
QString propName = mo->property(i).name();
auto prop = mo->property(i);
qDebug() << "Property: " << propName << "is an enum: " << prop.isEnumType();
}
return 0;
}
e1 id: 1024,valid: true,scope : Test_SameFile
e2 id: 1025,scope : Test_DiffFile
Property: "INT1" is an enum: false
Property: "ENUMVAL1" is an enum: true
Property: "ENUMVAL2" is an enum: false
如您所见,在与类相同的文件中声明的枚举在属性系统中按预期工作,但在头文件中声明的枚举未被识别为枚举。我该如何解决这个问题?我删除了构建文件夹,重新运行 qmake
,我能想到的所有明显的东西都没有改变。
解决方法
我相信为了让您的 enum
被 Qt
的元类型系统识别,它需要在 Q_OBJECT
或 Q_GADGET
中声明。如果您不想将其作为类的一部分(出于可理解的原因,例如可重用性等),您可以声明一个单独的结构,其中包含 Q_GADGET
宏,然后您可以定义您的 enum
那里。最重要的是,如果您希望 Qt
的元类型系统可以识别您的类型,但又不想将其设为 QObject
,则只需将其设为 {{ 1}}。 Q_GADGET
和 Q_OBJECT
之间的区别在于小工具不能有信号和槽。
所以,它看起来像这样:
Q_GADGET
你可以试试看是否有效。
,我尝试复制您的源代码,但我得到了所有这些案例的 true
。请看:
这是 EnumHolder.h
,它定义了两个命名空间 YoYo
和 YaYo
,分别包含枚举 Fruit
和 Vegetable
:
#ifndef ENUMHOLDER_H
#define ENUMHOLDER_H
#include <QMetaProperty>
namespace YoYo {
Q_NAMESPACE
enum Fruit {
Apple,Pear,Watermelon,};
Q_ENUM_NS(Fruit)
} // namespace YoYo
namespace YaYo {
Q_NAMESPACE
enum Vegetable {
Broccoli,Tomato,Lettuce,};
Q_ENUM_NS(Vegetable)
} // namespace YaYo
#endif // ENUMHOLDER_H
这是Food.h
,它定义了命名空间FoodType
中的枚举Embedded
,它还定义了一个名为QObject
的{{1}},它包含3个类型的属性Food
、YoYo::Fruit
和 YaYo::Vegetable
:
Embedded::FoodType
这是我的#ifndef FOOD_H
#define FOOD_H
#include <QMetaProperty>
#include <QObject>
#include "EnumHolder.h"
namespace Embedded {
Q_NAMESPACE
enum FoodType {
Food1,Food2,Food3,};
Q_ENUM_NS(FoodType)
} // namespace Embedded
class Food : public QObject {
Q_OBJECT
Q_PROPERTY(YoYo::Fruit fruit MEMBER _fruit)
Q_PROPERTY(YaYo::Vegetable vegetable MEMBER _vegetable)
Q_PROPERTY(Embedded::FoodType foodType MEMBER _foodType)
private:
YoYo::Fruit _fruit;
YaYo::Vegetable _vegetable;
Embedded::FoodType _foodType;
};
#endif // FOOD_H
:
main.cpp
这是我的输出:
int main(int argc,char *argv[]) {
QCoreApplication app(argc,argv);
Food food;
auto mo = food.metaObject();
for (int i = mo->propertyOffset(); i < mo->propertyCount(); ++i) {
auto property = mo->property(i);
qDebug() << property.name() << " is an enum: " << property.isEnumType();
}
return app.exec();
}
此外,我没有使用 fruit is an enum: true
vegetable is an enum: true
foodType is an enum: true
或 qRegisterMetaType()
。它只是按照现在的方式工作。
我想说的另一个注意事项是它可以作为概念证明,但这通常不是一个好主意,因为除非有需要,否则通常不想在代码中定义太多名称空间.在这里感觉就像将枚举放在单独的文件中一样,您必须定义一个包含 Q_DECLARE_META_TYPE
宏的新命名空间。我尝试重用相同的命名空间并在不同的头文件中定义另一个枚举,但出现 MOC 错误。对于给定的命名空间,您显然只能使用一次 Q_NAMESPACE
。如果您的枚举顶部没有它,则不能使用 Q_NAMESPACE
,因为您会收到另一个错误。
因此,拥有一个头文件可能是一个好主意,您将在其中定义命名空间中的所有枚举,这样您将仅对该命名空间使用一次 Q_ENUM_NS
并将所有这些枚举添加到 {{1} } 的元对象系统。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。