How to access C++ enum from QML?
Solution 1
You can wrap the enum in a class which derives from QObject (and that you expose to QML):
style.hpp :
#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:
#include <QApplication>
#include "style.hpp"
int main (int argc, char ** argv) {
QApplication a(argc, argv);
//...
StyleClass::declareQML();
//...
return a.exec();
}
QML Code:
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
//...
}
Solution 2
As of Qt 5.8 you can expose enums from a namespace
:
Define the namespace and enum:
#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
}
Register the namespace (eg. in main(), before creating a Qml View/Context):
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
);
Use it in a QML file:
import QtQuick 2.0
import my.namespace 1.0
Item {
Component.onCompleted: console.log(MyNamespace.STYLE_RADIAL)
}
References:
https://www.kdab.com/new-qt-5-8-meta-object-support-namespaces/
http://doc.qt.io/qt-5/qqmlengine.html#qmlRegisterUncreatableMetaObject
http://doc.qt.io/qt-5/qobject.html#Q_ENUM_NS
Solution 3
Additional information (not documented prior to Qt 5.5):
Your enum value names must start with a Capital letter.
This will work:
enum EnStyle
{
STYLE_RADIAL,
STYLE_ENVELOPE,
STYLE_FILLED
};
Q_ENUMS(EnStyle)
This does not:
enum EnStyle
{
styleRADIAL,
styleENVELOPE,
styleFILLED
};
Q_ENUMS(EnStyle)
You won't get any kind of error at compile time, they are just ignored by the QML engine.
Solution 4
I found a very nice solution for using ENUMs from C++ class in QML, here: Enums in Qt QML - qml.guide. The post was so good, I felt obliged to share it here with the SO community. And IMHO attribution should always be done, hence added the link to the post.
The post basically describes:
1) How to create an ENUM type in Qt/C++:
// statusclass.h
#include <QObject>
class StatusClass
{
Q_GADGET
public:
explicit StatusClass();
enum Value {
Null,
Ready,
Loading,
Error
};
Q_ENUM(Value)
};
2) How to register the class with QML engine as an "Uncreatable Type":
(This is the part which makes this solution nice and distinct.)
// main.cpp
...
QQmlApplicationEngine engine;
qmlRegisterUncreatableType<StatusClass>("qml.guide", 1, 0, "StatusClass",
"Not creatable as it is an enum type.");
...
Use of qmlRegisterUncreatableType
prevents instantiation of StatusClass
in QML. A warning will be logged if a user tries to instantiate this class:
qrc:/main.qml:16 Not creatable as it is an enum type.
3) Finally, how to use the ENUM in a QML file:
// 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.
}
}
Important note:
ENUM is supposed to be used by referencing it with the class name, like this StatusClass.Ready
. If the same class is also being used in QML as a context property...
// 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
...
...then, sometimes people accidentally use the ENUM with the context property instead of the class name.
// main.qml
...
Component.onCompleted: {
// Correct
console.log(StatusClass.Ready); // 1
// Wrong
console.log(statusClassObj.Ready); // undefined
}
...
The reason people tend to make this mistake is because Qt Creator's autocomplete feature lists ENUM as option, both when referencing using class name as well as the context property. So just exercise caution when in such a situation.
Solution 5
All this solutions can't enabled used this enum-class as parameter for signal/slot. This code compile, but not work in QML:
class DataEmitter : public QObject
{
Q_OBJECT
public:
...
signals:
void setStyle(StyleClass::EnStyle style);
}
...
emit setStyle(StyleClass.STYLE_RADIAL);
QML-part:
Connections {
target: dataEmitter
onSetStyle: {
myObject.style=style
}
}
And this code generate runtime error, as this:
IndicatorArea.qml:124: Error: Cannot assign [undefined] to int
For this code working, you must additional registry Qt metaobject type:
qRegisterMetaType<StyleClass::EnStyle>("StyleClass.EnStyle");
More details written here: https://webhamster.ru/mytetrashare/index/mtb0/1535044840rbtgvfmjys (rus)
![Aquarius_Girl](https://i.stack.imgur.com/s9JpE.jpg?s=256&g=1)
Aquarius_Girl
Arts and Crafts.stackexchange.com is in public beta now. Join us!
Updated on July 09, 2022Comments
-
Aquarius_Girl almost 2 years
class StyleClass : public QObject { public: typedef enum { STYLE_RADIAL, STYLE_ENVELOPE, STYLE_FILLED } Style; Style m_style; //... };
The .h file has the above code. How to access the above enum through QML?
-
Richard1403832 over 8 years@big_gie I refer the honourable gentleman to the phrase "as of posting", and the Qt bug report I made at the time. It is now documented because I took some actions to add it to the documentation.
-
big_gie over 8 yearsThanks for reporting it to Qt! Thanks to you the docs is in better shape now ;) I simply wanted to add (and refer to the exact location) that it is now documented.
-
DavidJ about 7 yearsWondering if there is a way for enums not in a QObject derived class (e.g. in a software layer below the UI without Qt dependencies).
-
Fabien almost 7 yearsNote: the class registered must provide a default constructor
-
air-dex almost 7 yearsYou're right. I have just edited my answer with additional details.
-
Alex Vallejo almost 7 years@DavidJ we are wondering the same thing. As far as I can tell you can't do this. Right now we are doing this:
enum MyEnum { Foo = MyOtherEnum::Foo }; Q_ENUMS(MyEnum)
-
Maxim Paperno over 6 years@DavidJ As of Qt v5.8 you can do it for enums in namespaces. See answer below.
-
Marc Van Daele over 5 yearsThis now also seems to be documented here: doc.qt.io/qt-5/…
-
KernelPanic almost 5 yearsThis is very nice solution, however, how does one compares enum with its value?
-
air-dex almost 5 years@KernelPanic Enums are integers in QML. So you can do something like
myitem.item_style === Style.STYLE_RADIAL
. -
slayer over 4 years@MaximPaperno How would you do this with a namespace enum in a header file that you are not able to modify? I tried to declare a new namespace and register the enum with a typedef like: typedef OtherEnumNamespace::OtherEnum NewEnum; Q_ENUM_NS(NewEnum) But it doesn't work
-
Maxim Paperno over 4 years@slayer Did you mean to post this under my answer below? :) I think it's a good question, perhaps deserving a separate post. Does
Q_ENUM_NS(OtherEnumNamespace::OtherEnum)
in your new NS (withQ_NAMESPACE
macro I presume) work? Maybeusing
instead oftypedef
for an alias? Just guessing! I think a new question might be the way to go. -
ScottG about 4 yearsA few years ago I spent the better part of a day trying to figure out why my enums weren't showing up in QML for this reason...
-
jhasse over 3 yearsAny way to use those enums in C++?
-
pooya13 about 3 yearsIn case you are wondering like me,
staticMetaObject
is an object added to your namespace by theQ_NAMESPACE
macro. -
hl037_ almost 3 yearsCouldn't it work with just a "using MyForeignEnum" in the class inheriting QObject ?
-
Matteo almost 3 yearsRemember to re-run qmake after you add Q_NAMESPACE or the build process will not find the staticMetaObject
-
Curtwagner1984 about 2 yearsThe solution works,, but Is there some way the IDE (Qt Creator) can support this? As in the intelisense picking up the enums on the QML side? Because as I see, right now you need to manually write the enum names.