5

Enums are not working out for me.

  • I have registered them with Q_ENUMS()
  • I did not forget the Q_OBJECT macro
  • the type is registered using qmlRegisterType()
  • the module is imported in QML

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

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

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.

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

and...

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

Output is:

0
1
0
1
2
3

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.

4

2 に答える 2

13

あなたの問題は列挙型の露出ではなく、先頭にアンダースコアがあるという事実です。それを取り除くと、それは機能します。

列挙値は大文字で始める必要があります。列挙型と添付プロパティを区別するには、何らかの規則が必要です。先頭の大文字は列挙型を参照し、残りは添付プロパティ (または設定されていない場合は未定義) を参照します。

確かに、Qt 自体にも警告があります。なぜなら、その enum 値を int または var プロパティに割り当てようとしても、現在警告を受けていないためです。現在のメンテナーとその問題について少し話し合ったところ、後で修正されるバグです。

対応して提案されたソリューションとともに、以下の作業コードを参照してください。

main.cpp

#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
于 2014-01-11T20:06:14.607 に答える