Integrating QML and C++

QML applications often need to handle more advanced and performance-intensive tasks in C++. The most common and quickest way to do this is to expose the C++ class to the QML runtime, provided the C++ implementation is derived from QObject. Assuming that you have Qt 5.7 or later installed, the following step-by-step instructions guide you through the process of using the C++ class, BackEnd, in a QML application:

  1. Create a new project using the "Qt Quick Application" template in Qt Creator

    Note: Uncheck the With ui.qml file option in the Define Project Details section of New Project Wizard.

  2. Add a new C++ class called BackEnd to the project and replace its header file contents with:
    #ifndef BACKEND_H
    #define BACKEND_H
    
    #include <QObject>
    #include <QString>
    #include <qqml.h>
    
    class BackEnd : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(QString userName READ userName WRITE setUserName NOTIFY userNameChanged)
        QML_ELEMENT
    
    public:
        explicit BackEnd(QObject *parent = nullptr);
    
        QString userName();
        void setUserName(const QString &userName);
    
    signals:
        void userNameChanged();
    
    private:
        QString m_userName;
    };
    
    #endif // BACKEND_H

    The Q_PROPERTY macro declares a property that could be accessed from QML. The QML_ELEMENT macro makes the BackEnd class available in QML.

  3. Add the following lines to your project file:
    CONFIG += qmltypes
    QML_IMPORT_NAME = io.qt.examples.backend
    QML_IMPORT_MAJOR_VERSION = 1

    The BackEnd class is automatically registered as a type, which is accessible from QML by importing the URL, "io.qt.examples.backend 1.0".

  4. Replace the contents of backend.cpp with:
    #include "backend.h"
    
    BackEnd::BackEnd(QObject *parent) :
        QObject(parent)
    {
    }
    
    QString BackEnd::userName()
    {
        return m_userName;
    }
    
    void BackEnd::setUserName(const QString &userName)
    {
        if (userName == m_userName)
            return;
    
        m_userName = userName;
        emit userNameChanged();
    }

    The setUserName function emits the userNameChanged signal every time m_userName value changes. The signal can be handled from QML using the onUserNameChanged handler.

  5. Replace the contents of main.qml with the following code:
    import QtQuick 2.6
    import QtQuick.Controls 2.0
    import io.qt.examples.backend 1.0
    
    ApplicationWindow {
        id: root
        width: 300
        height: 480
        visible: true
    
        BackEnd {
            id: backend
        }
    
        TextField {
            text: backend.userName
            placeholderText: qsTr("User name")
            anchors.centerIn: parent
    
            onEditingFinished: backend.userName = text
        }
    }

    The BackEnd instance lets you access the userName property, which is updated when the TextField's text property changes.

Now the application can be run.

Application running on Ubuntu

Qt offers several methods to integrate C++ with QML, and the method discussed in this tutorial is just one of them. For more details about these methods, refer to Overview - QML and C++ Integration.

© 2023 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.