[SOLVED] Displaying a C++ class via QML in QtQuick2

Issue

I am working on a QtQuick 2 application (Qt version 6.2.3). I created one C++ class (let’s call this class "Example") that contains the data that my application should deal with. This class can be instantiated several times, representing different datasets to be displayed.

class ExampleObject : public QObject {
    Q_OBJECT
    Q_PROPERTY(QString property1 MEMBER property1 CONSTANT)
    ...

    public:
    QString property1;
};

Q_DECLARE_METATYPE(ExampleObject*)

I want to be able to display instances of this class via QML, therefore I created a "Example" custom component with a property pointing to the Example C++ object containing the data I want to display.

ExampleComponent {
    property var exampleCppObject // exampleCppObject is a pointer to an instance of ExampleObject

    Label {
        text: exampleCppObject.property1
    }
}

To be able to change the Example instance used by the QML component, I created functions to "reinitialize" and "update" the component:

ExampleComponent {
    property var exampleCppObject // exampleCppObject is a pointer to an instance of ExampleObject
    property string textToDisplay

    function update() {
        textToDisplay=Qt.binding(() => exampleCppObject.property1);
    }

    function reinitialize() {
        textToDisplay=""
    }

    Label {
        text: textToDisplay
    }
}

I call these functions after changing or deleting the Example object pointed by ExampleCppObject, and this works quite fine. But I feel like this isn’t best practice, and it seems to me that I am doing things wrong.

What are better ways of connecting C++ to QML, in the situation I described?


Edit: my main.cpp essentially consists in:

MainModel mainModel;
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("mainModel", &mainModel);
engine.load(QStringLiteral("qrc:/main.qml"));

Where mainModel is an object which can create different instances of ExampleObject while the application is running.

Solution

You can optimize the binding textToDisplay such that you don’t have to call the upate and reinitialize functions, which seems to be the question you are after:

property var exampleCppObject
property string textToDisplay : exampleCppObject ? exampleCppObject.property1 : ""

In case you need more complex logic in the future, you can also use braces:

property string textToDisplay: {
    console.log("log me everytime the binding is reevalutated")
    if(condition1)
       return "invalid"
    else if(condition2)
       return exampleCppObject.property2
    else
       return exampleCppObject.property1
}

The best part of this, is that QQmlEngine actually reevaluates the binding for every property that is used in this binding (which has a notify signal), so if crafted correctly, you can largely leave the binding alone (meaning you don’t need the update and reinitialize function)

Answered By – Amfasis

Answer Checked By – Pedro (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *