Использование ENUMS из разных классов (или пространств имен) для слотов, вызываемых из QML - PullRequest
0 голосов
/ 13 июня 2018

У меня есть класс (например, MyEnumClass, Q_GADGET), в котором я определяю enum, например, MyEnum.
Я вызываю Q_ENUM(MyEnum), чтобы зарегистрировать его в метаобъекте и зарегистрировать веськласс как необработанный тип для QML.

Во втором моем классе (MyObject : QObject с макросом Q_OBJECT) у меня есть слот, который потребляет MyEnum в качестве параметра.Этот объект зарегистрирован как обычный тип для QML (создаваемый).

Я хочу вызвать слот из QML со значением из MyEnum - это не удается, так как тип MyEnumClass::MyEnum кажется неизвестным.

Когда enum определен внутри класса со слотом, он работает нормально.


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 ... безрезультатно.

Я также попытался поместить перечисление в пространство имен, как описано здесь - он также был непригоден для слота.

Единственный способ, которым я нашел вызов слота, - это удалить enum и использовать int в качестве типа для параметра - что не очень хорошо ...


Как я могу сделать эту работу?
Есть ли какие-то уловки, которые мне не хватает?

1 Ответ

0 голосов
/ 13 июня 2018

Метатип регистра:

qRegisterMetaType<MyEnumClass::MyEnum>();

Объяснение:

От Q_ENUM (...) документация:

Этот макрос регистрируетсятип enum с системой мета-объектов.Он должен быть помещен после объявления enum в класс, который имеет макрос Q_OBJECT или макрос Q_GADGET.Для пространств имен используйте вместо этого Q_ENUM_NS ().

...

Зарегистрированные перечисления автоматически регистрируются также в системе мета-типов Qt, делая их известными QMetaType без необходимости использования Q_DECLARE_METATYPE ().

Использование Q_ENUM автоматически регистрирует перечисление в мета-объектной системе, поэтому вам не нужно добавлять Q_DECLARE_METATYPE(MyEnum)

, но для использования перечисления в подключенных к очереди сигнальных слот-свойствах... вам нужно зарегистрировать метатип.

Как сказано в int qRegisterMetaType () документация:

Чтобы использовать тип T в QVariant, используйте Q_DECLARE_METATYPE () достаточно.Чтобы использовать тип T в соединениях с сигналами и слотами в очереди, qRegisterMetaType () должен быть вызван до установления первого соединения.

Кроме того, для использования типа T с API QObject :: property (), qRegisterMetaType ()должен вызываться перед его использованием, обычно в конструкторе класса, который использует T, или в функции main ().

...