How to connect a QML gui with a c++ application

Qt’s new gui toolkit QtQuick / QML has a really nice touch to it. Therefore it was time to play around with it. While playing around with it, but that proved a bit more confusion that (I think) is needed. Therefore this small tutorial to help you get started.

Interaction between the c++ application (backend) and the QML based gui is easier than it seems. However, most QML examples do not show any interaction with a backend c++ application, and most C++ - QML examples are described from the QML point of view and/or are to big to easily understand the concepts.

To tackle this problem I created a minimal example. You can download the example from my github. For completeness sake I will describe the main concepts here as well.

The example explained

The example application contains 4 files of interest: main.cpp, main.qml, testobject.cpp, and testobject.h. It is assumed that the application is started using the Qt Creator - Qt Quick Application Wizard (via File -> New File or Project). Also a new class named TestObject is created (including the .cpp and .h files). The TestObject is added as include in the main.cpp.

main.cpp

Only a few things are important in the main.cpp. First we need to include QQmlContext and later we need to set a QQmlContext property. This way QML knows about the properties’ objects and reference name:

engine.rootContext()->setContextProperty("testObject",&to);

where to is an instance of our TestObject and the TestObjects properties (read: signals and slots) are accecable in QML via the name testObject.

main.qml

In the QML file we added two visible components: a button and a label. Since we will interact with both components, we give them an id. The button receives an onClick event (read: signal) which will trigger the slot defined in our TestObject.

onClicked: {
    // Default button signal
    testObject.someSlot("fn-call")
}

We will also define a slot to catch signals from our c++ backend. When catching a signal from our backend, the string content of that signal is placed in the label.

Connections
{
    id:cppConnection
    target:testObject
    ignoreUnknownSignals: true
    onSomeSignal: {
        someTxt.text = text
    }
}

Note that the onSomeSignal property actually described a slot (hence, it catches the signal send from the C++ backend), and that the = text has this name because it is defined by that name in the .cpp and .h file.

testobject.h

The TestObject is a class derived from QObject. In our example the class implements one signal and one slot:

signals:
    void someSignal(const QString &text);

public slots:
    void someSlot(const QString &text);

Which are implemented in the cpp file.

testobject.cpp

The slot is a very simple function. It implements the slot and emits a new signal to change the label text.

void TestObject::someSlot(const QString &text)
{
    QString nText = text + ".cpp";
    emit someSignal(nText);

    qDebug() << nText;
}

Note that you need to include QDebug to use the debug function.

Finally…

I hope that this little example helped. Once more, check the full source code and working example at my github repository.