Saturday, April 2, 2011

Signal Slot connection with QML and Qt C++ code

As you might already know, currently I am working on porting of my existing Qt application to QML. And while doing so I required to interconnect QML code to C++ code using signal slot.

Honestly, I found it quite cumbersome to connect QML signal to Qt C++ slot. I decided to avoid connecting QML signal to Qt Slot and instead choose to expose slot from Qt to QML,which it can invoke from any QML file. As it's quite convenient to expose Qt slot to QML element.

Connecting Qt signal to QML is quite easy. We can use Connections component to connect Qt signal to QML element.

Following code is exposing Qt C++ Object to QML, so QML elements can invoke Qt slot.
    TimerObject timerObj;
    QDeclarativeView view;
    view.setResizeMode(QDeclarativeView::SizeRootObjectToView);
    QDeclarativeContext *ctxt = view.rootContext();
    ctxt->setContextProperty("timer", &timerObj);

    view.setSource(QUrl("qrc:/main.qml"));
    view.show();

So, now we can use "timer" object from QML to invoke C++ slot. like shown in below.
Button {
    anchors.horizontalCenter:parent.horizontalCenter
    text: "Start Timer"
    width: parent.width/2

    onClicked: {
       timer.startStopTimer();
    }
}
If you want to use Button element used in above code visit this link.

Following code is connecting signal emitted from Qt C++ to QML. below I am connecting TimerObject's (timer in QML) timeChanged signal to QML element using Connection component.
    Connections {
        target:timer
        onTimeChanged: {
            clock.text = "<h1>"+time+"</h1>"
        }
    }

timeChanged signal is defined like following in C++ code.
signals:
    void timeChanged(QString time);

9 comments:

  1. Kunal-

    Thanks a lot for posting this example. Exactly what I have been trying to do. 4.7 documentation is pretty weak on QML "Connections" syntax... not sure I ever would have figured it out!

    ReplyDelete
  2. Thank you for comment. I am glad that it helped you.

    ReplyDelete
  3. Hi Kunal thanks for the trick.
    However if you have an item inside another item in the QML, how do you bind it?
    QDeclarativeContext *ctxt = view.rootContext();
    ctxt->setContextProperty("timer", &timerObj);

    the property timer is in the rootView only. I guess some C++ code need to be changed. Thanks

    ReplyDelete
  4. How can I receive a signal from C++ in QML , if I change it in C++ code ?

    ReplyDelete
    Replies
    1. above code sample does exactly same thing, it shows how you can capture timeChanged() c++ signal in QML.

      Delete
  5. Hi,

    Any idea of how to do the last part :

    signals:
    void timeChanged(QString time);

    in python/PySide ?

    ReplyDelete
  6. Hi, Had a query regarding slots. How can I start an external program within QT using this slot mechanism ?

    ReplyDelete
    Replies
    1. you can use QProcess to launch externa program and then attach signal slot to QProcess's signal/slot

      Delete