Mohamed Jihed Jaouadi
Mohamed Jihed Jaouadi

Reputation: 1517

Calling a QML function from C++

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;
            ...
        }
}

Upvotes: 10

Views: 31069

Answers (4)

Sherif O.
Sherif O.

Reputation: 514

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();

Upvotes: 0

user3545770
user3545770

Reputation: 363

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.

Upvotes: 3

SourabhKus
SourabhKus

Reputation: 828

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.

Upvotes: 16

Dinesh
Dinesh

Reputation: 489

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");
 }
}

Upvotes: 18

Related Questions