class StyleClass : public QObject {
public:
typedef enum
{
STYLE_RADIAL,
STYLE_ENVELOPE,
STYLE_FILLED
} Style;
Style m_style;
//...
};
上述代码在.h文件中。如何通过QML访问上述枚举?
#ifndef STYLE_HPP
#define STYLE_HPP
#include <QtGlobal>
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
// Qt 4
#include <QDeclarativeEngine>
#else
// Qt 5
#include <QQmlEngine>
#endif
// Required derivation from QObject
class StyleClass : public QObject
{
Q_OBJECT
public:
// Default constructor, required for classes you expose to QML.
StyleClass() : QObject() {}
enum EnStyle
{
STYLE_RADIAL,
STYLE_ENVELOPE,
STYLE_FILLED
};
Q_ENUMS(EnStyle)
// Do not forget to declare your class to the QML system.
static void declareQML() {
qmlRegisterType<StyleClass>("MyQMLEnums", 13, 37, "Style");
}
};
#endif // STYLE_HPP
主函数.cpp:
#include <QApplication>
#include "style.hpp"
int main (int argc, char ** argv) {
QApplication a(argc, argv);
//...
StyleClass::declareQML();
//...
return a.exec();
}
QML 代码:
import MyQMLEnums 13.37
import QtQuick 2.0 // Or 1.1 depending on your Qt version
Item {
id: myitem
//...
property int item_style: Style.STYLE_RADIAL
//...
}
从Qt5.8开始,您可以从一个namespace
中公开枚举:
定义命名空间和枚举:
#include <QObject>
namespace MyNamespace
{
Q_NAMESPACE // required for meta object creation
enum EnStyle {
STYLE_RADIAL,
STYLE_ENVELOPE,
STYLE_FILLED
};
Q_ENUM_NS(EnStyle) // register the enum in meta object data
}
在创建Qml视图/上下文之前,注册命名空间(例如在main()函数中):
qmlRegisterUncreatableMetaObject(
MyNamespace::staticMetaObject, // meta object created by Q_NAMESPACE macro
"my.namespace", // import statement (can be any string)
1, 0, // major and minor version of the import
"MyNamespace", // name in QML (does not have to match C++ name)
"Error: only enums" // error in case someone tries to create a MyNamespace object
);
在QML文件中使用它:
import QtQuick 2.0
import my.namespace 1.0
Item {
Component.onCompleted: console.log(MyNamespace.STYLE_RADIAL)
}
参考文献:
https://www.kdab.com/new-qt-5-8-meta-object-support-namespaces/
http://doc.qt.io/qt-5/qqmlengine.html#qmlRegisterUncreatableMetaObject
staticMetaObject
是通过 Q_NAMESPACE
宏添加到你的命名空间中的一个对象。 - pooya13额外信息(Qt 5.5之前未记录):
您的枚举值名称必须以大写字母开头。
这样做是可行的:
enum EnStyle
{
STYLE_RADIAL,
STYLE_ENVELOPE,
STYLE_FILLED
};
Q_ENUMS(EnStyle)
这不会:
enum EnStyle
{
styleRADIAL,
styleENVELOPE,
styleFILLED
};
Q_ENUMS(EnStyle)
在编译时,您不会收到任何错误提示,它们只是被QML引擎忽略掉了。
我在这里找到了一个非常好的解决方案,可以在QML中使用C++类中的ENUM,链接如下:Enums in Qt QML - qml.guide。该帖子非常好,我觉得有必要与SO社区分享,并且我认为应该始终进行归属声明,因此添加了帖子的链接。
该帖子基本上描述了:
1)如何在Qt/C++中创建ENUM类型:
// statusclass.h
#include <QObject>
class StatusClass
{
Q_GADGET
public:
explicit StatusClass();
enum Value {
Null,
Ready,
Loading,
Error
};
Q_ENUM(Value)
};
2)如何将类注册到QML引擎作为“不可创建类型”:
(这是使此解决方案美观且独特的部分。)
// main.cpp
...
QQmlApplicationEngine engine;
qmlRegisterUncreatableType<StatusClass>("qml.guide", 1, 0, "StatusClass",
"Not creatable as it is an enum type.");
...
使用qmlRegisterUncreatableType
可以防止在QML中实例化StatusClass
。如果用户尝试实例化这个类,将会记录警告:
使用qmlRegisterUncreatableType
可以防止在QML中实例化StatusClass
。如果用户尝试实例化这个类,将会记录警告:
qrc:/main.qml:16 Not creatable as it is an enum type.
3) 最后,如何在 QML 文件中使用 ENUM:
// main.qml
import QtQuick 2.9
import QtQuick.Window 2.2
import qml.guide 1.0
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Component.onCompleted: {
console.log(StatusClass.Ready); // <--- Here's how to use the ENUM.
}
}
重要提示:
应该使用类名引用ENUM,格式如下:StatusClass.Ready
。如果与同一类在QML中作为上下文属性使用…
// main.cpp
...
QQmlApplicationEngine engine;
qmlRegisterUncreatableType<StatusClass>("qml.guide", 1, 0, "StatusClass",
"Not creatable as it is an enum type.");
StatusClass statusClassObj; // Named such (perhaps poorly) for the sake of clarity in the example.
engine.rootContext()->setContextProperty("statusClassObj", &statusClassObj); // <--- like this
...
...然后,有时人们会意外地在ENUM中使用上下文属性而不是类名。
// main.qml
...
Component.onCompleted: {
// Correct
console.log(StatusClass.Ready); // 1
// Wrong
console.log(statusClassObj.Ready); // undefined
}
...
人们容易犯这个错误的原因是因为Qt Creator的自动完成功能在使用类名和上下文属性引用时都将ENUM列为选项。所以在这种情况下要小心谨慎。自Qt 5.10起,Qt还支持使用QML定义枚举类型。除了air-dex提供的基于C ++的答案之外,现在你也可以使用QML创建枚举类型:
Style.qml:
import QtQuick 2.0
QtObject {
enum EnStyle {
STYLE_RADIAL,
STYLE_ENVELOPE,
STYLE_FILLED
}
}
如果您只想在 QML 代码中使用这些枚举,那么这个解决方案会简单得多。您可以通过 qml 中的 Style 类型访问上述枚举,例如:
import VPlayApps 1.0
import QtQuick 2.9
App {
property int enStyle: Style.EnStyle.STYLE_RADIAL
Component.onCompleted: {
if(enStyle === Style.EnStyle.STYLE_ENVELOPE)
console.log("ENVELOPE")
else
console.log("NOT ENVELOPE")
}
}
点击这里,可以看到基于QML的枚举类型的另一个使用示例。
所有这些解决方案都不能将此枚举类用作信号/槽参数。这段代码可以编译,但在QML中无法工作:
class DataEmitter : public QObject
{
Q_OBJECT
public:
...
signals:
void setStyle(StyleClass::EnStyle style);
}
...
emit setStyle(StyleClass.STYLE_RADIAL);
QML部分:
Connections {
target: dataEmitter
onSetStyle: {
myObject.style=style
}
}
这段代码会产生运行时错误,如下所示:
IndicatorArea.qml:124: Error: Cannot assign [undefined] to int
qRegisterMetaType<StyleClass::EnStyle>("StyleClass.EnStyle");
QML_ELEMENT
和Q_ENUM()
(不是已弃用的Q_ENUMS()
)。由于该类是QObject,所以应该已经具有Q_OBJECT
,以便在Qt MOC系统中进行注册。class StyleClass : public QObject {
Q_OBJECT // Let the MOC know about this QObject
QML_ELEMENT // Make this object available to QML
public:
typedef enum
{
STYLE_RADIAL,
STYLE_ENVELOPE,
STYLE_FILLED
} Style;
Style m_style;
Q_ENUM(Style) // Make this enum available to QML
//...
};
{ClassName}.{EnumValue}
来访问枚举,而无需引用枚举名称。例如:StyleClass.STYLE_RADIAL
。我的变量(为了向后兼容,当命名空间不可用时,请使用手动预定义的宏 ENABLE_USE_ENUM_NAMESPACES):
// enum.h
#pragma once
#include <QObject>
#ifndef ENABLE_USE_ENUM_NAMESPACES
class TaskTypeEnums : public QObject
{
Q_OBJECT
Q_ENUMS(TaskTypeEnum)
public:
explicit TaskTypeEnums(QObject *parent = nullptr): QObject(parent) {}
#else
namespace TaskTypeEnums {
Q_NAMESPACE
#endif
enum TaskTypeEnum {
TaskConnectDev,
TaskDisconnectDev,
TaskPingDev,
TaskResetDev,
TaskTakeControlDev,
TaskSetAkaModDev,
TaskFirmwareUpdDev,
TaskConnectDevs,
TaskDisconnectAll,
TaskMainTestSot,
TaskMainTestBA,
};
#ifndef ENABLE_USE_ENUM_NAMESPACES
};
#else
Q_ENUM_NS(TaskTypeEnum)
}
#endif
// ----------------------------------------------------------------------------
// fragment from main.cpp
//...
#ifdef ENABLE_USE_ENUM_NAMESPACES
qmlRegisterUncreatableMetaObject(TaskTypeEnums::staticMetaObject, "Vip.Enums.Tasks", 1, 0, "Tasks", "");
#else
qmlRegisterType<TaskTypeEnums>("Vip.Enums.Tasks", 1, 0, "Tasks");
#endif
//...
enum MyEnum { Foo = MyOtherEnum::Foo }; Q_ENUMS(MyEnum)
。 - Alex Vallejo