Exposing C++ backend to QML

  • Hi

    I can see two methods: qmlRegisterType and setContextProperty
    Is it possible to register backend.h in main.cpp which then will be exposed in main.qml

    import io.qt.examples.backend 1.0
    BackEnd {
            id: backend

    And then if I create "QList<QObject*> dataList" of some sort in backend.cpp or its child classes I can use this as a model for example for Repeater somewhere in qml files eg. like this:

    Repeater {
        model: backend.someClass.dataList

    The idea is to have single "entry point" from QML to C++ classes

    Will this work?

    Best Regards

  • Well this will not work.

    Digging deeper, I would like some clarify this:
    I have created subclassed QAbstractListModel based on this Sailfish nice example
    If I register this model:

    qmlRegisterType<DemoModel>("com.example", 1, 0, "DemoModel");

    I can't pass any arguments during registration - according to this: QML needs to be able to instantiate the type, calling it with only parent QObject.
    So if my model needs to get the data from C++ part of the application, eg. from xmlMgr that reads files from directory, it can't be exposed to QML with qmlRegisterType - am I get this right?

    In case model needs to get data from C++ part I need to use

    demoModel=new DemoModel(xmlMgr);
    view.rootContext()->setContextProperty("demoModel", demoModel);

    Is this how it supposed to be, or am I missing something?

    Best Regards

  • @Marek If you have one object which you have created in C++ you can expose that object to be used in QML with setContextProperty. If a model is based on QAbstractItemModel and can be used automatically in C++ views it should work automatically with QML views, too. So I think your last comment is correct - you need only setContextProperty for it to work.

  • @Eeli-K Thanks for answer.
    I hoped someone will add something about qmlRegisterType used with models (first approach), because as I see it now... it pretty much useless for registering models

    Best Regards

  • Hi @Marek,

    you don't need to create any instances of DemoModel in your C++. qmlRegisterType is enough, but you also need somehow to trigger update of your model. In my case I've created Q_INVOKABLE void update(); method in my model's class implementation which is being called each time data in model should be refreshed.
    Of course don't forget to override:
    int rowCount(const QModelIndex &parent);
    QVariant data(const QModelIndex &index, int role);
    methods in your model implementation.
    Here you have great description of model-view-delegate concept: http://doc.qt.io/qt-5/model-view-programming.html

  • Hi @osmial

    I don't create DemoModel instance in C++. I know it will be created by QML and I know about Q_INVOKABLE.
    Lets say you have some cpp class dataMgr - it reads data from external source like tcp socket.
    This Data is needed for DemoModel, and you have DemoModel defined in cpp.
    How do you call DemoModel Q_INVOKABLE void update() from QML if DemoMode does not know about dataMgr ?
    DemoModel is instantiated in QML without pointer to dataMgr and you cant access DataModel from cpp.

    I assume that your update() from DemoModel reads data from some source but this process is completely isolated from the rest of cpp part of application, right?

    Best Regards

  • I have ended up with such a solution:

    int main(int argc, char *argv[])
        QGuiApplication app(argc, argv);
        QQmlApplicationEngine engine;
        BackEnd backend(&engine);
        if (engine.rootObjects().isEmpty())
            return -1;
        return app.exec();

    Backend contructor is before engine load so the models are defined in QML
    Backend init is after engine load to get rootObject, signals etc.

    Backend - C++ part of the application

    #include "backend.h"
    BackEnd::BackEnd(QQmlApplicationEngine *engine) {
        xmlMgr=new XmlMgr(this);
        itemModel=new ItemModel(this);
        context = engine->rootContext();
    void BackEnd::init() {
    void BackEnd::itemClicked(int item_id) {
        qDebug()<<"BackEnd::itemClicked item_id:"<<item_id;
        int catalog_id=itemModel->getCatalogId(item_id);

    QML part

    ApplicationWindow {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
        signal itemClicked(int value)
        header: Header {
            height: 60;
            width: parent.width
        SwipeView {
            id: swipeView
            anchors.fill: parent
            Page1 {
            Page {
                MainItem2 {
                    id: mainItem
                    visible: true

    This works well for me.

    Best Regards

Log in to reply

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.