将来自不同类(或名称空间)的ENUMS用于从QML调用的插槽

der*_*erM 3 enums qt qml qt5

我有一个类(例如MyEnumClass,Q_GADGET),其中我限定enum,例如MyEnum.
我调用Q_ENUM(MyEnum)它将它注册到metaobject,并将整个类注册为QML的不可创建类型.

在我的第二个类(MyObject : QObject使用宏Q_OBJECT)中,我有一个使用MyEnumas参数的插槽.此对象作为常规类型注册到QML(可创建).

我想从QML调用带有值的插槽MyEnum- 这会失败,因为Type MyEnumClass::MyEnum似乎未知.

当使用插槽在类中定义枚举时,它可以正常工作.


MVCE

class MyEnumClass {
    Q_GADGET
public:
    enum MyEnum {
        E1,
        E2,
        E3
    };
    Q_ENUM(MyEnum)
};


class MyObject : public QObject
{
    Q_OBJECT

public:
    MyObject(QObject* parent = nullptr) : QObject(parent) {}

    enum TestEnum {
        V1,
        V2,
        V3
    };
    Q_ENUM(TestEnum)

public slots:
    void testFun1(MyEnumClass::MyEnum val) { qDebug() << val; }
    void testFun2(TestEnum val) { qDebug() << val; }
};
Run Code Online (Sandbox Code Playgroud)

在main.cpp中:

qmlRegisterUncreatableType<MyEnumClass>("MyObject", 1, 0, "MyEnum", "Uncreatable");
qmlRegisterType<MyObject>("MyObject", 1, 0, "MyObject");
Run Code Online (Sandbox Code Playgroud)

在main.qml中:

import MyObject 1.0
ApplicationWindow {
    id: window
    visible: true
    width: 600
    height: 600

    MyObject {
        id: obj
    }

    MouseArea {
        anchors.fill: parent
        onClicked: {
            console.log(MyObject.V2)
            console.log(MyEnum.E2)
            obj.testFun2(MyObject.V2)
            obj.testFun1(MyEnum.E1)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我试图继承MyEnumClassMyObject作出的枚举部分MyObject,我用不同的宏和函数试图让更多的可供选择MetaObjectSystem枚举......无济于事.

我还尝试在这里描述的命名空间中放置一个枚举- 它也无法用于插槽.

我发现调用插槽的唯一方法是删除枚举并使用int作为参数的类型 - 这不是那么好......


我怎样才能做到这一点?
有没有我缺少的技巧?

Eli*_*kis 7

注册元型:

qRegisterMetaType<MyEnumClass::MyEnum>();
Run Code Online (Sandbox Code Playgroud)

说明:

来自Q_ENUM(...)文档:

此宏使用元对象系统注册枚举类型.它必须放在具有Q_OBJECT或Q_GADGET宏的类中的枚举声明之后.对于名称空间,请使用Q_ENUM_NS().

...

已注册的枚举也会自动注册到Qt元类型系统,使QMetaType知道它们,而无需使用Q_DECLARE_METATYPE().

使用Q_ENUM自动将枚举与元对象系统一起注册,因此您无需添加 Q_DECLARE_METATYPE(MyEnum)

但是要在排队的信号槽连接中使用枚举,属性......你需要注册元类型.

如在int qRegisterMetaType()文档中所述:

要在QVariant中使用类型T,使用Q_DECLARE_METATYPE()就足够了.要在排队信号和插槽连接中使用类型T,必须在建立第一个连接之前调用qRegisterMetaType().

此外,要将类型T与QObject :: property()API一起使用,必须在使用qRegisterMetaType()之前调用它,通常在使用T的类的构造函数中,或在main()函数中.