在QML信号中公开枚举

Exposing an enum in a QML signal

本文关键字:枚举 QML 信号      更新时间:2023-10-16

我在qml中使用正确的enum类型接收信号mySignal有问题。我想我做的每件事都是对的:

  • 枚举在一个单独的类中,派生自QObject
  • 注册到Q_ENUMS
  • 包含枚举的类注册到qmlRegisterUncreatableType
  • 定义信号的类,也是QObject,也注册在qmlRegisterUncreatableType

值得注意的事实:

  • 运行程序在main调用的槽中打印日志。qml中没有接收到发出的信号。
  • 取消textclass.cpp中的emit注释允许在QML中接收信号,但不会触发与enum值的比较。

为什么我没有在QML中接收到带有enum的信号,为什么我不能与QML中的enum值进行比较,即使它与Q_ENUMS一起暴露?

我在Qt缺陷页面上看到了一个关于枚举的缺陷报告,所以我理解Qt中对枚举的支持不是坚如磐石。然而,我真的希望能够比较值的枚举在QML中接收到的信号,目前我没有。由于某种原因,输入到mySlot中的值很乐意接受与信号处理程序中无法识别的枚举值相同的值。代码清单如下。

在Ubuntu上使用Qt 5.4。

error.h:

#ifndef ERROR_H
#define ERROR_H
#include <QObject>
#include <QtQml>
class Error : public QObject
{
    Q_OBJECT
    Q_ENUMS(Type)
public:
    explicit Error(QObject *parent = 0) {Q_UNUSED(parent)};
    ~Error() {};
    static void RegisterTypes(void)
    {
        qmlRegisterUncreatableType<Error>("Types", 1, 0, "Error", "Error class uncreatable");
    }
    enum Type {
        OK = 0,
        FILE_ERROR
    };
};
#endif // ERROR_H

testclass.h:

#ifndef TESTCLASS_H
#define TESTCLASS_H
#include <QObject>
#include <QVariant>
#include <QDebug>
#include "error.h"
class TestClass : public QObject
{
    Q_OBJECT
public:
    explicit TestClass(QObject *parent = 0);
    ~TestClass();
    static void RegisterTypes(void)
    {
        qmlRegisterUncreatableType<TestClass>("TestClass", 1, 0, "TestClass", "TestClass uncreatable");
    };
signals:
    void mySignal(Error::Type arg);
    void mySignal(int arg);
public slots:
    void mySlot(QVariant arg);
};
#endif // TESTCLASS_H

testclass.cpp:

#include "testclass.h"
TestClass::TestClass(QObject *parent) : QObject(parent)
{
}
TestClass::~TestClass()
{
}
void TestClass::mySlot(QVariant arg)
{
    qDebug() << "mySlot called" << arg.toInt();
    int retval = static_cast<int>(arg.toInt());
    emit mySignal(static_cast<Error::Type>(retval));
    //   emit mySignal(retval);
}

main.cpp:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtQml>
#include "error.h"
#include "testclass.h"
int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;
    Error::RegisterTypes();
    TestClass::RegisterTypes();
    TestClass* tPtr = new TestClass();
    engine.rootContext()->setContextProperty("_t", tPtr);
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    return app.exec();
}

main.qml:

import QtQuick 2.4
import QtQuick.Window 2.2
import Types 1.0
import TestClass 1.0
Window {
    visible: true
    width: button.width + 20
    height: button.height + 20
    Rectangle {
        id: button
        width: theText.width + 20
        height: theText.height + 20
        anchors.margins: 10
        anchors.centerIn: parent
        border.width: 3
        Connections {
            target: _t
            onMySignal: {
                console.log("onMySignal: ", arg)
                if (arg == Error.OK) {
                    console.log("OK")
                }
                else if (arg == Error.FILE_ERROR) {
                    console.log("FILE_ERROR")
                }
                else {
                    console.log("UNDEFINED")
                }
            }
        }
        Text {
            id: theText
            anchors.centerIn: parent
            text: "press me!"
            font.pixelSize: 30
        }
        MouseArea {
            anchors.fill: parent
            onClicked: _t.mySlot(Error.FILE_ERROR)
            onPressed: button.scale = 0.9
            onReleased: button.scale = 1.0
        }
    }
}

这个问题是双重的。

第一个问题:

  • 错误::类型未在元类型系统中注册下面一行需要添加到Error类声明之后:

    Q_DECLARE_METATYPE(错误:类型)

第二个问题:

  • 是我为错误选择了名称'Error'当我注册它的时候。这与内置的类型相冲突。的注册需要更改为:

    qmlRegisterUncreatableType("Types", 1,0, "ErrorClass", "Error class uncreatable");

    (QML代码也需要更新以反映这一点课程。)

改变这两件事解决了问题,信号现在可以在qml代码中正确接收。