如何从 QML 访问 C++ 枚举?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20089196/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 22:54:40  来源:igfitidea点击:

How to access C++ enum from QML?

c++qtqmlqtquick2

提问by Aquarius_Girl

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?

.h 文件具有上述代码。如何通过 QML 访问上述枚举?

回答by air-dex

You can wrap the enum in a class which derives from QObject (and that you expose to QML):

您可以将枚举包装在从 QObject 派生的类中(并且您向 QML 公开):

style.hpp :

样式.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:

主.cpp:

#include <QApplication>
#include "style.hpp"

int main (int argc, char ** argv) {
    QApplication a(argc, argv);

    //...

    StyleClass::declareQML();

    //...

    return a.exec();
}

QML Code:

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

    //...
}

回答by Maxim Paperno

As of Qt 5.8you can expose enums from a namespace:

从 Qt 5.8 开始,您可以从 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):

注册命名空间(例如,在 main() 中,在创建 Qml 视图/上下文之前):

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
);

Use it in a QML file:

在 QML 文件中使用它:

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/

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/qqmlengine.html#qmlRegisterUncreatableMetaObject

http://doc.qt.io/qt-5/qobject.html#Q_ENUM_NS

http://doc.qt.io/qt-5/qobject.html#Q_ENUM_NS

回答by Richard1403832

Additional information (not documented prior to Qt 5.5):

附加信息(在Qt 5.5之前未记录):

Your enum value names muststart 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.

您在编译时不会遇到任何类型的错误,它们只是被 QML 引擎忽略。

回答by GDevT

Qt also supports QML-defined enum types since Qt version 5.10. As an alternative to the C++-based answer by air-dex, you can now also use QML to create enum types:

自 Qt 5.10 版起,Qt 还支持 QML 定义的枚举类型。作为 air-dex 基于 C++ 的答案的替代方案,您现在还可以使用 QML 创建枚举类型:

Style.qml:

样式.qml:

import QtQuick 2.0

QtObject {
  enum EnStyle {
    STYLE_RADIAL,
    STYLE_ENVELOPE,
    STYLE_FILLED
  }
}

If you only intend to use the enums in your QML code, this solution is much simpler. You can access the above enum with the Style type in qml then, for example:

如果您只想在 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")
  }
}

See herefor another usage example of a QML-based enum type.

有关基于 QML 的枚举类型的另一个使用示例,请参见此处

回答by Xintrea

All this solutions can't enabled used this enum-class as parameter for signal/slot. This code compile, but not work in QML:

无法启用所有这些解决方案,使用此枚举类作为信号/插槽的参数。这段代码可以编译,但在 QML 中不起作用:

class DataEmitter : public QObject
{
    Q_OBJECT

public:
    ...
signals:
    void setStyle(StyleClass::EnStyle style);
}

...

emit setStyle(StyleClass.STYLE_RADIAL);

QML-part:

QML-部分:

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:

对于此代码工作,您必须附加注册表 Qt 元对象类型:

qRegisterMetaType<StyleClass::EnStyle>("StyleClass.EnStyle");

More details written here: https://webhamster.ru/mytetrashare/index/mtb0/1535044840rbtgvfmjys(rus)

更多细节写在这里:https://webhamster.ru/mytetrashare/index/mtb0/1535044840rbtgvfmjys(俄罗斯)

回答by zeFree

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.

我找到了一个非常好的解决方案,用于在 QML 中使用来自 C++ 类的 ENUM,这里: Qt QML 中的 Enums - qml.guide。这篇文章太好了,我觉得有必要在这里与 SO 社区分享。恕我直言,应该始终进行归因,因此添加了帖子的链接。

The post basically describes:

该帖子主要描述了:

1) How to create an ENUM type in Qt/C++:

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) How to register the class with QML engine as an "Uncreatable Type":
(This is the part which makes this solution nice and distinct.)

2)如何使用 QML 引擎将类注册为“不可创建的类型”:(
这是使这个解决方案很好和独特的部分。)

// main.cpp

...
QQmlApplicationEngine engine;
qmlRegisterUncreatableType<StatusClass>("qml.guide", 1, 0, "StatusClass",
                                        "Not creatable as it is an enum type.");
...

Use of qmlRegisterUncreatableTypeprevents instantiation of StatusClassin QML. A warning will be logged if a user tries to instantiate this class:

使用qmlRegisterUncreatableType防止StatusClass在 QML 中的实例化。如果用户尝试实例化此类,则会记录警告:

qrc:/main.qml:16 Not creatable as it is an enum type.

3) Finally, how to use the ENUM in a QML file:

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.
    }
}

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...

重要说明:
应该通过使用类名引用它来使用 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
...

...then, sometimes people accidentally use the ENUM with the context property instead of the class name.

...然后,有时人们会不小心将 ENUM 与上下文属性而不是类名一起使用。

// 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.

人们倾向于犯这个错误的原因是因为Qt Creator 的自动完成功能将 ENUM 列为选项,在使用类名和上下文属性进行引用时。因此,在这种情况下,请谨慎行事。

回答by cmannett85

Make the mocaware of your enum using the Q_ENUMSmacro, as described in the docs. You must register the class that 'owns' the enum beforeit is used, as described in the docs.

moc知道使用您的枚举的Q_ENUMS宏,作为描述文档。您必须使用枚举之前注册“拥有”枚举的类,如文档中所述。

Ashif's quote block is only valid if the enum is a global or is owned by a non-QObjectderived class.

Ashif 的引用块仅在枚举是全局的或由非QObject派生类拥有时才有效。