15

In C++ I have a class with an invokable function, what I would like to do is call that method from QML/Javascript (this I've gotten to work) and pass it a Javascript callback.

In code, I define my class like:

class MyObject: public QObject
{

Q_OBJECT

public:
    Q_INVOKABLE void doSomething(quint64 x, /* what goes here? */ jsCallback)
    {
        x += 1;

        // I suspect this will require a invocation mechanism but 
        // this shows what I'd like to do
        jsCallback(x);
    }
};

And in my QML, I would like to do something like:

Rectangle {

    function myCallback(x){
        console.log("x=" + x);
    }

    MouseArea{
        anchors.fill: parent
        onClicked:{
            myObject.doSomething(2, myCallback);
        }
    }
}

So that when I click on the Rectangle, I would see x=3 in the console. How would I define the parameter in C++ and invoke the callback in order to accomplish this?

Thank you!

1 Answer 1

18

I think I've figured this out. What I ended up doing was implementing this in my C++ class like such:

class MyObject: public QObject
{

Q_OBJECT

public:
    Q_INVOKABLE void doSomething(quint64 x, QJSValue jsCallback)
    {
        x += 1;

        QJSValue val = jsCallback.engine()->newObject();
        val.setProperty("x", x);

        jsCallback.call(QJSValueList { val });
    }
};

And then I can access the value in my callback like:

function myCallback(x){
    console.log("x=" + x.x);
}
Sign up to request clarification or add additional context in comments.

4 Comments

Also if you use in lambda function inside function (for example, after network reply), pass QJSValue as mutable \ by value.
Can anyone clarify if this is considered good practice? I'm facing a similar problem where I want to push an Item onto a StackView but only after an asynchronous operation (called from QML, implemented in C++) is finished
As of now QJSValue::engine() is deprecated but there's no suggested replacement in the Qt documentation. I'd be great to have an updated answer accounting for this.
Since Qt5.5, assuming MyObject is being invoked from a script running in a QJSEngine (or QQmlEngine), the current engine instance can be obtained with qjsEngine(this) (or qmlEngine(this)). doc.qt.io/qt-6/qjsengine.html#qjsEnginex

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.