Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QML: passing JS object to C++ member function

I'm trying to pass a JS object (map) to a C++ member function with a signature

Q_INVOKABLE virtual bool generate(QObject* context);

by using

a.generate({foo: "bar"});

The method is called (detected via breakpoint), but the passed context parameter is NULL. Since the documentation mentions that JS objects will be passed as QVariantMap, I've tried using the signature

Q_INVOKABLE virtual bool generate(QVariantMap* context);

but this failed during MOC. Using

Q_INVOKABLE virtual bool generate(QVariantMap& context);

causes the method to not be found at runtime by QML (error message is "Unknown method parameter type: QVariantMap&").

The documentation only has an example of passing a QVariantMap from C++ to QML, not in the other direction.

Using a public slot instead of a Q_INVOKABLE shows exactly the same behavior and errors.

like image 523
pmf Avatar asked Nov 14 '17 13:11

pmf


1 Answers

Don't use references to pass values from QML world to CPP world. This simple example works:

test.h

#ifndef TEST_H
#define TEST_H

#include <QObject>
#include <QDebug>
#include <QVariantMap>

class Test : public QObject
{
    Q_OBJECT
public:
    Test(){}

    Q_INVOKABLE bool generate(QVariantMap context)
    {qDebug() << context;}
};

#endif // TEST_H

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "test.h"

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;

    engine.rootContext()->setContextProperty(QStringLiteral("Test"), new Test());

    engine.load(QUrl(QLatin1String("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

main.qml

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    MouseArea
    {
        anchors.fill: parent
        onClicked:
        {
            Test.generate({foo: "bar"});
        }
    }
}

click in window, this will print following msg in output console:

QMap(("foo", QVariant(QString, "bar")))
like image 77
Xplatforms Avatar answered Sep 18 '22 01:09

Xplatforms