How to access C++ enum from QML?
1 2 3 4 5 6 7 8 9 10 11 12 | class StyleClass : public QObject { public: typedef enum { STYLE_RADIAL, STYLE_ENVELOPE, STYLE_FILLED } Style; Style m_style; //... }; |
.h文件具有上面的代码。 如何通过QML访问上述枚举?
您可以将枚举包装在从QObject派生的类中(并将其暴露给QML):
style.hpp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #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 |
main.cpp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #include <QApplication> #include"style.hpp" int main (int argc, char ** argv) { QApplication a(argc, argv); //... StyleClass::declareQML(); //... return a.exec(); } |
QML代码:
1 2 3 4 5 6 7 8 9 10 11 12 | 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 //... } |
从Qt 5.8开始,您可以从
定义名称空间和枚举:
1 2 3 4 5 6 7 8 9 10 11 12 | #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()中):
1 2 3 4 5 6 7 | qmlRegisterUncreatableMetaObject( MyNamespace::staticMetaObject, // static meta object "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文件中使用它:
1 2 3 4 5 6 | import QtQuick 2.0 import my.namespace 1.0 Item { Component.onCompleted: console.log(MyNamespace.STYLE_RADIAL) } |
参考文献:
http://doc.qt.io/qt-5/qqmlengine.html#qmlRegisterUncreatableMetaObject
http://doc.qt.io/qt-5/qobject.html#Q_ENUM_NS
附加信息(Qt 5.5之前未记录):
您的枚举值名称必须以大写字母开头。
这将起作用:
1 2 3 4 5 6 7 | enum EnStyle { STYLE_RADIAL, STYLE_ENVELOPE, STYLE_FILLED }; Q_ENUMS(EnStyle) |
这不是:
1 2 3 4 5 6 7 | enum EnStyle { styleRADIAL, styleENVELOPE, styleFILLED }; Q_ENUMS(EnStyle) |
您不会在编译时收到任何错误,QML引擎只会忽略它们。
从Qt版本5.10开始,Qt还支持QML定义的枚举类型。作为air-dex基于C ++的答案的替代方法,您现在还可以使用QML创建枚举类型:
Style.qml:
1 2 3 4 5 6 7 8 9 | import QtQuick 2.0 QtObject { enum EnStyle { STYLE_RADIAL, STYLE_ENVELOPE, STYLE_FILLED } } |
如果您只打算在QML代码中使用枚举,则此解决方案要简单得多。您可以使用qml中的Style类型访问上述枚举,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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的枚举类型的另一个用法示例,请参见此处。
如文档中所述,使用
Ashif的quote块仅在枚举是全局变量或由非
使用此枚举类作为信号/插槽的参数无法启用所有这些解决方案。该代码可以编译,但不能在QML中使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 | class DataEmitter : public QObject { Q_OBJECT public: ... signals: void setStyle(StyleClass::EnStyle style); } ... emit setStyle(StyleClass.STYLE_RADIAL); |
QML部分:
1 2 3 4 5 6 | Connections { target: dataEmitter onSetStyle: { myObject.style=style } } |
并且此代码生成运行时错误,如下所示:
1 | IndicatorArea.qml:124: Error: Cannot assign [undefined] to int |
为了使此代码正常工作,您必须附加注册表Qt元对象类型:
1 | qRegisterMetaType<StyleClass::EnStyle>("StyleClass.EnStyle"); |
此处写入更多详细信息:https://webhamster.ru/mytetrashare/index/mtb0/1535044840rbtgvfmjys(rus)
我找到了一个非常好的解决方案,用于在QML中使用C ++类中的ENUM:
Qt QML中的枚举-qml.guide。该帖子非常好,我有义务在此与SO社区分享。并且IMHO归因应始终执行,因此将链接添加到帖子中。
该帖子主要描述:
1)如何在Qt / C ++中创建ENUM类型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | // statusclass.h #include <QObject> class StatusClass { Q_GADGET public: explicit StatusClass(); enum Value { Null, Ready, Loading, Error }; Q_ENUM(Value) }; |
2)如何使用QML引擎将类注册为"无法创建的类型":
(这是使该解决方案美观而独特的部分。)
1 2 3 4 5 6 7 | // main.cpp ... QQmlApplicationEngine engine; qmlRegisterUncreatableType<StatusClass>("qml.guide", 1, 0,"StatusClass", "Not creatable as it is an enum type."); ... |
使用
1 | qrc:/main.qml:16 Not creatable as it is an enum type. |
3)最后,如何在QML文件中使用ENUM:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // 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与类名一起引用来使用ENUM,例如
1 2 3 4 5 6 7 8 9 10 | // 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与context属性而不是类名一起使用。
1 2 3 4 5 6 7 8 9 10 11 | // main.qml ... Component.onCompleted: { // Correct console.log(StatusClass.Ready); // 1 // Wrong console.log(statusClassObj.Ready); // undefined } ... |
人们倾向于犯此错误的原因是,在使用类名和上下文属性进行引用时,Qt Creator的自动完成功能将ENUM列为选项。因此,在这种情况下请谨慎行事。