IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Exposing State from C++ to QML

Description of how to expose global state from C++ to QML.

Article lu   fois.

L'auteur

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

Exposing State from C++ to QML

It is often desirable to expose some properties from C++ to all QML elements in a particular component, all QML elements in a module, or even all QML elements overall. You can do this by introducing singletons or by adding properties to the root objects of select components.

Using Singletons

If you want to expose a number of global properties to all elements in a module or all elements overall, you can define a singleton in C++. To do this, add the QML_ELEMENT or QML_NAMED_ELEMENT macros and the QML_SINGLETON macro to a class containing the properties you want to expose as Q_PROPERTY declarations:

 
Sélectionnez
// Singleton.h
class Singleton : public QObject
{
    Q_OBJECT
    Q_PROPERTY(int thing READ thing WRITE setThing NOTIFY thingChanged FINAL)
    QML_ELEMENT
    QML_SINGLETON

public:
    Singleton(QObject *parent = nullptr) : QObject(parent) {}

    int thing() const { return m_value; }
    void setThing(int v)
    {
        if (v != m_value) {
            m_value = v;
            emit thingChanged();
        }
    }

signals:
    void thingChanged();

private:
    int m_value = 12;
};

Now you can access the thing property of the singleton from any QML code that imports this module:

 
Sélectionnez
import QtQml

QtObject {
    objectName: "The thing is " + Singleton.thing
}

If you have placed your QML files in the same directory as the module (which is highly recommended), the singleton is available from the implicit import within your module. You don't need to import anything explicitly. If not, or if you want to access the thing property from other modules, you do need to import the module the singleton belongs to.

In order to set the value of the property from C++, you may need to retrieve the singleton instance. For this purpose you may use QQmlEngine::singletonInstance. The preferred way to do this is by giving a module and type name as parameters:

 
Sélectionnez
    Singleton *singleton
            = engine->singletonInstance<Singleton *>("MyModule", "Singleton");
    singleton->setThing(77);

Using Object Properties

If you want to expose some properties to only the QML elements in a specific component, you can add them as regular properties to the root object of the component. In order to make sure they are actually set in all cases, you can make them Required Properties. You might write your QML component as follows:

 
Sélectionnez
pragma ComponentBehavior: Bound

import QtQuick

Window {
    id: root
    visible: true

    required property int thing

    Text {
        anchors.fill: parent
        text: "The thing is " + root.thing
    }

    component Inner: QtObject {
        objectName: "I can see " + root.thing + " because I'm bound."
    }
}

We use an ID for the root element of the component and reference the property by ID and name from any inner objects. In order to safely make the ID of the root element available to any nested components, we use ComponentBehavior.

Then, in C++, when you create an object from such a component, you need to make sure to call the QQmlComponent::createWithInitialProperties, QQmlApplicationEngine::setInitialProperties, or QQuickView::setInitialProperties in order to initialize the properties. For example:

 
Sélectionnez
    QQmlEngine engine;

    QQmlComponent component(&engine, "MyModule", "RequiredProperties");
    QScopedPointer<QObject> o(component.createWithInitialProperties({
            {"thing", 11}
    }));

This is assuming your module URI is MyModule and the module is available in the QML import path.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+