Аргументы для сигнала C ++ отображаются как «неопределенные» внутри QML, когда QObject передается по ссылке - PullRequest
1 голос
/ 11 июля 2019

У меня есть объект C ++ с сигналом, который я подключил к обработчику QML.Однако, хотя я передаю аргументы в сигнал, аргументы QML отображаются как undefined.

с Balloon и Air в качестве пользовательских QObject s, я подключаюсь 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.

1 Ответ

1 голос
/ 11 июля 2019

По любой причине, QML не поддерживает параметры опорного сигнала.Вы передаете air по const&:

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

Чтобы это работало, вам нужно передать неконстантный указатель:

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

// ...

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

Обратите внимание, что безопасно передать указатель на выделенный стек air; QML не становится владельцем этого:

Когда данные переносятся из C ++ в QML, владение данными всегда остается за C ++ [если только QObject не возвращается из явногоВызов метода C ++].

...