Q_ENUMS 是“未定义的";在 QML 中?

2022-01-19 00:00:00 qt qtquick2 qml qt-signals c++

枚举不适合我.

  • 我已经用 Q_ENUMS()
  • 注册了它们
  • 我没有忘记 Q_OBJECT
  • 使用 qmlRegisterType()
  • 注册类型
  • 模块被导入到 QML 中

简而言之,一切都是按部就班",但出于某种原因,我继续为 QML 中的每个枚举获取 undefined.我错过了什么吗?

In short, everything is "by-the-book" but for some reason I continue getting undefined for each and every enum in QML. Am I missing something?

class UI : public QQuickItem {
    Q_OBJECT
    Q_ENUMS(ObjectType)
public:
enum ObjectType {
        _Root = 0,
        _Block
    };
...
};

...

qmlRegisterType<UI>("Nodes", 1, 0, "UI");

...

import Nodes 1.0
...
console.log(UI._Root) // undefined

另请注意,已注册的枚举确实可用于元系统,由于某种原因,它们在 QML 中不起作用.

Also note that the registered enums are indeed available to use for the metasystem, for some reason they do not work in QML.

更新:我刚刚发现了这个错误:https://bugreports.qt.io/browse/QTBUG-33248但与那个错误不同的是,我的根组件是一个纯 UI 不是以 UI 为根的自定义元素.

UPDATE: I just found this bug: https://bugreports.qt.io/browse/QTBUG-33248 But unlike that bug my root component is a bare UI not a custom element with UI as its root.

事实证明实际上可以在console.log()中使用QML中的枚举值,下面的代码实际上是可以工作的.

Turns out that it is actually possible to use enum values form QML in console.log(), the following code is actually working.

class A : public QObject {
    Q_OBJECT
    Q_ENUMS(EA)
public:
    enum EA {
        EA_NULL = 0,
        EA_ONE
    };
};

class B : public A {
    Q_OBJECT
    Q_ENUMS(EB)
public:
    enum EB {
        EA_TWO = 2,
        EA_THREE
    };
};

#include "main.moc"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    qmlRegisterType<A>("test", 1, 0, "A");
    qmlRegisterType<B>("test", 1, 0, "B");

    QtQuick2ApplicationViewer viewer;
    viewer.setMainQmlFile(QStringLiteral("qml/enums/main.qml"));
    viewer.showExpanded();

    return app.exec();
}

还有……

Component.onCompleted: {
        console.log(A.EA_NULL)
        console.log(A.EA_ONE)

        console.log(B.EA_NULL)
        console.log(B.EA_ONE)
        console.log(B.EA_TWO)
        console.log(B.EA_THREE)
    }

输出是:

0
1
0
1
2
3

所以我猜除了你没有正确使用它"之外还有另一个问题......这可能与我上面提到的错误有关,以及当我实例化 UI 时元素,我实际上实例化了一个 QML 组件,它是一个以 UI 为根的对象树.虽然这对于使用来自 C++ 的指针和完整的 QML 对象并没有任何问题,但它似乎出于某种原因弄乱了枚举.

So I guess there is another problem besides "you are not using it correctly"... It might have to do with the bug I mentioned above, and the fact that when I instantiate the UI element, I actually instantiate a QML component which is a tree of objects with the UI as the root. While this doesn't prove to be any problem for working with pointers from C++ with the full QML objects, it does seem to mess enums for some reason.

推荐答案

你的问题不是枚举的暴露,而是你有一个前导下划线.一旦你删除它,它就会起作用.

Your problem is not the exposure of the enum, but the fact that you have a leading underscore. Once you remove that, it will work.

您需要以大写字母开头的枚举值.需要一些规则来区分枚举与附加属性和枚举.前导大写表示枚举,其余表示附加属性(如果未设置,则为未定义).

You need to start the enum value with uppercase letter. Some rule is necessary to distinguish enums from attached properties from enums. Leading uppercase will refer to enums, and the rest for attached properties (or undefined if not set).

诚然,Qt 本身也有一个警告,因为如果您尝试将该枚举值分配给一个 int 或 var 属性,您目前没有收到警告,并且已经与当前维护者讨论了这个问题,这似乎是一个错误,稍后将修复.

Admittedly, there is also a warning in Qt itself because if you try to assign that enum value to an int or var property, you are currently not getting a warning, and having discussed that issue a little bit with the current maintainer, it seems to be a bug which will be fixed later on.

请参阅下面的工作代码以及相应建议的解决方案:

See the working code below with the correspondigly proposed solution:

#include <QQuickView>
#include <QQuickItem>

#include <QGuiApplication>

#include <QUrl>

class UI : public QQuickItem {
    Q_OBJECT
    Q_ENUMS(ObjectType)
public:
enum ObjectType {
        Root = 0,
        _Block
    };
};

#include "main.moc"

int main(int argc, char **argv)
{
    QGuiApplication guiApplication(argc, argv);
    qmlRegisterType<UI>("Nodes", 1, 0, "UI");
    QQuickView *view = new QQuickView;
    view->setSource(QUrl::fromLocalFile("main.qml"));
    view->show();
    return guiApplication.exec();
}

main.qml

import Nodes 1.0
import QtQuick 2.0

Rectangle {
    id: button
    width: 500; height: 500

    MouseArea {
        anchors.fill: parent
        onClicked: console.log(UI.Root)
    }
}

main.pro

TEMPLATE = app
TARGET = main
QT += quick
SOURCES += main.cpp

构建并运行

qmake && make && ./main

输出

0

相关文章