Connecter une logique à votre interface utilisateur QML

Connectez un moteur pour réaliser des calculs et fournir à votre interface utilisateur les données à afficher.

Pour intégrer la logique dans l'application, nous avons besoin de classes du moteur C++, pouvant effectuer les calculs importants. L'écriture de la logique dans les fichiers QML est déconseillée. Essayez donc de transférer le plus possible vers le moteur, de sorte que QML ne soit utilisé que pour afficher l'interface utilisateur, ce pour quoi il est le plus adapté.

Pour votre nouvelle classe de moteur, veuillez créer deux nouveaux fichiers appelés « backend.cpp » et « backend.h ». N'oubliez pas d'ajouter le nouveau fichier « cpp » à l'exécutable dans le fichier « src/CMakeLists.txt », à côté du fichier « main.cpp ».

Ajoutez le contenu suivant au nouveau fichier d'en-tête (celui ayant l'extension « .h ») :

#pragma once

#include <QObject>

class Backend : public QObject
{
    Q_OBJECT

public:
    explicit Backend(QObject *parent = nullptr);
};

Le fichier « cpp » contenant les définitions est vide pour l'instant. Il devrait contenir quelque chose comme ceci :

#include "backend.h"

Backend::Backend(QObject *parent)
    : QObject(parent)
{

}

Actuellement, l'interface utilisateur ne connaît pas la classe de votre moteur. Pour changer cela, nous devons enregistrer le nouveau type dans « main.cpp ». Le moteur sera créé comme un singleton, ce qui signifie qu'il ne sera créé qu'une seule fois et existera pendant toute la durée de l'application, de son démarrage à sa fermeture.

Dans le fichier « main.cpp », juste après avoir créé l'objet « QQmlApplicationEngine », ajoutez l'enregistrement de type comme ceci :

    Backend backend;
    qmlRegisterSingletonInstance<Backend>("org.kde.example", 1, 0, "Backend", &backend);

N'oubliez pas d'inclure le nouveau fichier d'en-tête en haut de « main.cpp ».

A partir de maintenant, le moteur sera connu de QML sous le nom de « Moteur ». Il est contenu dans un module appelé « org.kde.example ». Puisque le module fait partie de l'application, vous n'avez pas besoin de vous soucier de sa version, restez-en à la version 1.0 et utiliser le de manière cohérente dans l'application.

Dans le fichier « main.qml », importez le nouveau module :

import org.kde.example 1.0

Maintenant, nous avons connecté la classe contenant la future logique de l'application, mais elle ne fait toujours rien. Pour changer cela, ajoutons une propriété à la classe. Les propriétés sont bien plus qu'une simple variable. Elles peuvent informer l'interface utilisateur de tout changement afin qu'elle puisse mettre à jour les bonnes zones.

Juste sous la macro « Q_OBJECT », ajoutez une nouvelle « Q_PROPERTY ».

Q_PROPERTY(QString introductionText READ introductionText WRITE setIntroductionText NOTIFY introductionTextChanged)

Cela semble beaucoup pour une simple propriété que nous allons utiliser pour afficher du texte depuis le moteur, n'est-ce pas ? Mais, un regard plus attentif révèle que cela peut déjà exécuter de façon logique lorsque la propriété est lue par l'interface utilisateur et lorsqu'elle est écrite. Il informera automatiquement l'interface graphique et le moteur de tout changement.

La lecture et l'écriture reposent sur des fonctions « getter » et « setter ». Ainsi, pour ajouter un nouvel attribut privé à votre classe, comme ceci, puis ajoutez les fonctions « getter » et « setter ».

private:
    QString m_introductionText = "Hello World!";

Dans la section publique, ajoutez

    QString introductionText() const;
    void setIntroductionText(const QString &introductionText);
    Q_SIGNAL void introductionTextChanged();

La première fonction est « getter », la deuxième « setter » et la troisième un signal étant émis lorsque la propriété a été modifiée. Le signal n'a pas besoin d'implémentation dans le fichier « cpp », puisqu'il ne fait rien de plus que d'être émis. Cependant, les fonctions « getter » et « setter » doivent être implémentés de la manière suivante :

QString Backend::introductionText() const
{
    return m_introductionText;
}

void Backend::setIntroductionText(const QString &introductionText)
{
    m_introductionText = introductionText;
    Q_EMIT introductionTextChanged();
}

Comme vous pouvez le voir, lorsque le transmetteur est appelé, le signal sera émis et informera l'interface utilisateur et le moteur de ce changement.

Pour afficher le texte, ajoutez dans « main.qml » un titre l'affichant juste sous la propriété de texte de l'élément « Kirigami.Page », déjà contenu dans le modèle.

Le code résultant dans cette partie du fichier devrait ressembler à ceci :

        ...
        Kirigami.Page {
            title: i18n("develop.kde.org tutorial")

            Kirigami.Heading {
                anchors.centerIn: parent
                text: Backend.introductionText
            }

            actions {
                main: Kirigami.Action {
                    ...

Maintenant, compiler et lancer votre programme à nouveau.

Félicitations, vous êtes formé :

  • Comment enregistrer des types de moteurs dans QML
  • Ajouter de nouveaux éléments au fichier QML
  • Créer des sous-classes nouvelles de QObject
  • Comment ajouter des propriétés et ce qu'elles font
  • Quels signaux sont

Si vous souhaitez en savoir plus sur l'intégration entre QML et C++, nous vous recommandons la lecture de la documentation officielle de Qt.