当通过引用传递 QObject 时,C++ 信号的参数在 QML 中显示为“未定义”

Arguments to C++ signal show up as `undefined` inside QML when a QObject is passed by reference

我有一个 C++ 对象,它带有一个连接到 QML 处理程序的信号。但是,即使我将参数传递给信号,QML 参数也会显示为 undefined.

BalloonAir 作为自定义 QObject,我将 Balloon 的信号 void popped(Air const& air, int volume, QString message); 连接到 QML 处理程序:

Balloon.qml:

import QtQuick 2.12
import QtQuick.Controls 2.12

import ReproImpl 0.1 as Impl

Item {
    id: root
    width: 500
    height: 500

    property int sharpness: 50

    readonly property Impl.Balloon impl: Impl.Balloon {
        onPopped: {
            // Output: {}
            console.log(JSON.stringify(arguments));
            // TypeError: cannot read property 'type' of undefined
            console.log("Bang!", air.type, volume, message);
        }
    }

    Button {
        anchors.centerIn: parent
        text: "Click me"

        onClicked: {
            console.log("Clicked!");
            impl.prick(sharpness)
        }
    }
}

main.cpp:

#include <QGuiApplication>
#include <QObject>
#include <QQmlEngine>
#include <QQuickView>

namespace my::ns {
    // Used as a parameter of the signal
    class Air : public QObject {
        Q_OBJECT
        Q_PROPERTY(QString type READ type)

    public:
        Air(QString type, QObject* parent = nullptr)
            : QObject{parent}
            , type_{type}
        {}

        Air(QObject* parent = nullptr)
            : Air{"", parent}
        {}

        QString type() const { return type_; }

    private:
        QString type_;
    };


    class Balloon : public QObject {
        Q_OBJECT

    public:
        Balloon(int toughness, QObject* parent = nullptr)
            : QObject{parent}
            , toughness{toughness}
        {}

        Balloon(QObject* parent = nullptr)
            : Balloon{10, parent}
        {}

    Q_SIGNALS:
        void popped(Air const& air, int volume, QString message);

    public Q_SLOTS:
        void prick(int sharpness)
        {
            if (sharpness > toughness) {
                Air air{"Hello"};
                Q_EMIT popped(air, 10, "POP!");
            }
        }

    private:
        int toughness;
    };

    void registerModule()
    {
        qmlRegisterModule("ReproImpl", 0, 1);
        qmlRegisterType<Air>("ReproImpl", 0, 1, "Air");
        qmlRegisterType<Balloon>("ReproImpl", 0, 1, "Balloon");
        qmlProtectModule("ReproImpl", 0);
    }
}

int main(int argc, char** argv)
{
    QGuiApplication app(argc, argv);

    my::ns::registerModule();

    QQuickView window(QUrl("Balloon.qml"));
    window.show();

    return app.exec();
}

#include "main.moc"

我该怎么做才能解决这个问题?

这发生在 Qt 5.12.0 和 5.13.0 中。

出于某种原因,QML 不支持参考信号参数。您正在通过 const&:

传递 air
void popped(Air const& air, int volume, QString message);

要使其正常工作,您需要传递一个 non-const 指针:

void popped(Air* air, int volume, QString message);

// ...

void prick(int sharpness)
{
    if (sharpness > toughness) {
        Air air{"Hello"};
        Q_EMIT popped(&air, 10, "POP!");
    }
}

请注意,将指针传递给分配的堆栈是安全的airQML does not take ownership 其中:

When data is transferred from C++ to QML, the ownership of the data always remains with C++ [unless a QObject is returned from an explicit C++ method call].