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

时间:2018-06-13 10:55:34

标签: qt enums qml qt5

我有一个班级(例如MyEnumClassQ_GADGET),其中我定义了enum,例如MyEnum
我调用Q_ENUM(MyEnum)将它注册到元对象,并将整个类注册为QML。

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

我想使用MyEnum中的值来调用QML中的插槽 - 这会失败,因为类型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; }
};

在main.cpp中:

qmlRegisterUncreatableType<MyEnumClass>("MyObject", 1, 0, "MyEnum", "Uncreatable");
qmlRegisterType<MyObject>("MyObject", 1, 0, "MyObject");

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

我尝试继承MyEnumClass中的MyObject来制作MyObject的枚举部分,我尝试使用不同的宏和函数来使枚举在MetaObjectSystem中更加可用...无济于事。

我还尝试将枚举放在here所描述的命名空间中 - 它也无法用于插槽。

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

我怎样才能做到这一点?
我缺少任何技巧吗?

1 个答案:

答案 0 :(得分:7)

注册元类型:

qRegisterMetaType<MyEnumClass::MyEnum>();

说明:

来自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()函数中。