Calling a QML function from C++
Asked Answered
A

4

10

I'm developing a Blackberry 10 mobile application using the BB Native SDK.

I need to call a QML function into my C++ class. I searched a lot on this but I only found the possibility to call C++ into QML not the inverse. You can check this: QML and C++ integration

Can anyone help me on this?

This is the QML code specifying the function that I need to call which add a marker into my mapview:

Container {
    id: pinContainer
    objectName: "pinContObject"
        ...

        function addPin(lat, lon, name, address) {
            var marker = pin.createObject();
            marker.lat = lat;
            marker.lon = lon;
            ...
        }
}
Arriola answered 15/11, 2013 at 11:38 Comment(0)
M
18

Thats what signals and slots are for. You can use the QML Connections for connecting arbitrary signals to arbitrary slots in QML.

http://qt-project.org/doc/qt-4.8/qml-connections.html

  Container {
            id: pinContainer
            objectName: "pinContObject"
            ...

            function addPin(lat, lon, name, address) {
                var marker = pin.createObject();
                marker.lat = lat;
                marker.lon = lon;
                ...
            }

            Connections {
                target: backend
                onDoAddPin: { 
                  addPin(latitude, longitude,name, address)
                }
            }
     }

and in C++ backend, all you have to do is

class Backend: public QObject {
signals:
    void doAddPin(float latitude, float longitude, QString name, QString address);

 ........
 void callAddPinInQML(){
     emit doAddPin( 12.34, 45.67, "hello", "world");
 }
}
Marianamariand answered 15/11, 2013 at 13:25 Comment(3)
Really greatfull for your answer !!! but how to pass parameters in c++ and affect it to the qml function parameters ?Arriola
Updated the example to pass function parameters via. signals. The javascript function/variable scoping rules apply if there are any namespace collisions of the variables with the function params of the signals. Good Luck :)Marianamariand
Thx ^_^ !! But unfortunately, when I try to run the application in my BB device, it doesn't want to load; I checked and I found that there is a problem when I add the connection property in the QML file. I'm really confused :/Arriola
H
16

MyItem.qml

import QtQuick 2.0
  Item {
    function myQmlFunction(msg) {
      console.log("Got message:", msg)
      return "some return value"
  }
}

main.cpp

QQmlEngine engine;
QQmlComponent component(&engine, "MyItem.qml");
QObject *object = component.create();

QVariant returnedValue;
QVariant msg = "Hello from C++";
QMetaObject::invokeMethod(object, "myQmlFunction",
    Q_RETURN_ARG(QVariant, returnedValue),
    Q_ARG(QVariant, msg));

qDebug() << "QML function returned:" << returnedValue.toString();
delete object;

This should works. Here i am calling a QML function from my C++ class.

Hyaline answered 9/5, 2014 at 8:40 Comment(3)
This is exactly the code which can be found at Qt's documentation: [doc.qt.io/qt-5/…Pessa
Qt's documentation is good enough but people don't have time to read them. They need specific info quickly that i provided.Hyaline
You should still give credits, though. Or even provide the link to the docsIcarus
P
3

From Qt documentation:

http://qt-project.org/doc/qt-5/qtqml-cppintegration-interactqmlfromcpp.html#invoking-qml-methods

Calling QMetaObject::invokeMethod one will call proper slot, no matter if it is defined in C++ or QML.

Plainsman answered 24/8, 2014 at 19:45 Comment(0)
S
0

there is another way using binding, when the value of some x value is changed on Cpp side and it is binded on the qml side, the onchange will be called on qml side. This solution is easier and more direct than connecting signal-to-signal as noticed here, however if you want to transfer data within the signal I recommend to use signal-signal connection

ex:

qml side

    import com.drOmranConsulting.backend 1.0

    BackEnd {
        id: _backend
    }

Page1Form {
     objectName: "page1box"

        /* property alias recchange: _backend.rec_x
           signal rec_xChanged is transmitted from C++
           when rec_x is newly set. To receive this signal
           an alias is used in qml side to the value rec_x
           the binding will be updated upon signal emitting
        */
        property alias recXchange: _backend.rec_x

    onRecXchangeChanged:
        {
           console.log("signal received")
           console.log(" the x coordinate is changed on cpp side to " + _backend.getRecX() )
           _rect.x=_backend.getRecX()
        }
     }

backend.h

signals:
    void rec_xChanged();            /* cpp emits signal rec_xChanged             */
                                    /* when rec_x value has been changed         */
                                    /* in QML: value is aliased using            */
                                    /* property alias recchange: _backend.rec_x  */
                                    /* detecing signal at onRecchangeChanged     */

in main.cpp

//Backend class Initialization
backend Backend;
qmlRegisterType<backend>("com.drOmranConsulting.backend",1,0,"BackEnd");

in backend.cpp

emit rec_xChanged();
Skin answered 30/11, 2021 at 22:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.