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

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Qt Quick Discussion :

Des exemples sur l’intégration du QML avec C++ [Débuter]


Sujet :

Qt Quick

  1. #1
    Futur Membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Septembre 2014
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Septembre 2014
    Messages : 3
    Points : 7
    Points
    7
    Par défaut Des exemples sur l’intégration du QML avec C++
    Bonjour tout le monde,

    Je suis en train de faire un projet avec Qt , mais mon interface graphique nécessite plus d'animation. J'ai trouvé que le Qml pourra m'aider pour faire des animations un peu fluide , mais j'ai un peu de problème avec l’intégration de C++ avec Qml ( comme par exemple la lecture d'un fichier text pour récupérer les données en suite les afficher .....) .

    Est ce que je pourrai avoir des exemples à propos l’intégration du QML avec C++ ?
    La documentation sur QML/C++ est un peu restreinte .

    Merci d'avance,

  2. #2
    Rédacteur
    Avatar de Amnell
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2009
    Messages
    1 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 840
    Points : 5 545
    Points
    5 545
    Par défaut
    Bonjour,

    En ce qui concerne la communication C++/QML, vous avez deux grandes méthodes de communication, à utiliser selon ce que vous souhaitez faire. Pour illustrer ces exemple, je pars du main.cpp et du main.qml suivants, en Qt 5.3 :

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
     
        QQmlApplicationEngine engine;
        engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
     
        return app.exec();
    }

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import QtQuick 2.2
    import QtQuick.Window 2.1
     
    Window {
        visible: true
        width: 360
        height: 360
     
        Text {
            text: "Hello World!"
            anchors.centerIn: parent
        }
    }

    La première approche touche le cas que vous abordez, c'est-à-dire une simple transmission d'informations du C++ vers le QML. Pour ce cas précis, QML propose les propriétés contextuelles (context properties) qui permettent en fait au QML d'accéder à une information du C++ (variable, instance d'une classe héritant de QObject, etc.) par le biais d'un nom. Prenons l'exemple de la lecture d'un fichier :

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    QString text;
    QFile f("file.txt");
    if (f.open(QIODevice::ReadOnly | QIODevice::Text))
        text = f.readAll();
    else
        text = f.errorString();
     
    QQmlApplicationEngine engine;
    // Définition d'une propriété contextuelle nommée "textContents" contenant ce qu'il y a dans le fichier file.txt
    engine.rootContext()->setContextProperty("textContents", text);
    engine.load(QUrl(QStringLiteral("qrc:///main.qml")));

    Du côté du QML, on peut alors exploiter cela, en modifiant par exemple le Hello World par le contenu du fichier :

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Text {
        text: textContents // accès à la propriété contextuelle
        anchors.centerIn: parent
    }

    Prenons un exemple plus complexe où l'on souhaite lire un fichier au moment où l'utilisateur va cliquer sur la fenêtre. Il s'agit là de remonter un événement du QML vers le C++. Cette fois-ci, on passera toujours par une propriété contextuelle mais celle-ci ne contiendra pas une variable de type QString mais plutôt un pointeur vers une instance d'une classe que l'on définit ici :

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #ifndef MYREADER_H
    #define MYREADER_H
     
    #include <QObject>
    #include <QFile>
     
    class MyReader : public QObject // Héritage de QObject pour pouvoir définir l'instance en tant que propriété contextuelle
    {
        Q_OBJECT // Nécessaire pour la communication du QML vers le C++
     
    public:
        MyReader() {}
     
    public slots:
        QString getFileContents(const QString &path) { // Déclaré en tant que slot pour pouvoir être appelé par le QML
            QFile f(path);
            if (f.open(QIODevice::ReadOnly | QIODevice::Text))
                return f.readAll();
            return f.errorString();
        }
    };
     
    #endif // MYREADER_H

    La déclaration de la propriété contextuelle :

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    MyReader reader; // Instance de notre classe
    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("textReader", &reader); // Assignation de l'instance en tant que propriété contextuelle
    engine.load(QUrl(QStringLiteral("qrc:///main.qml")));

    Et l'utilisation du QML, avec la MouseArea permettant de recevoir le clic et l'appel au C++ depuis le QML lors de celui-ci :

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    Window {
        visible: true
        width: 360
        height: 360
     
        Text {
            id: myText
            anchors.centerIn: parent
        }
     
        MouseArea {
            anchors.fill: parent
            // Appel au C++ depuis le QML et assignation du résultat au texte du composant Text
            onClicked: myText.text = textReader.getFileContents("file.txt");
        }
    }

    En général, le fait d'avoir une interface graphique va faire que c'est toujours l'interface graphique qui va commander des calculs dans le C++, à moins qu'il y ait présence de threads C++, mais je préfère ne pas aborder ce cas ici. Le premier cas de figure précédemment expliqué permet donc de visualiser comment faire une communication du QML vers le C++ sous différents cas de figure. Abordons maintenant la deuxième méthode de communication C++/QML : l'extension de QML avec des objets C++.

    Il peut arriver que l'on ne trouve pas les éléments que l'on souhaite dans QML. Par exemple, on pourrait vouloir utiliser un composant QML de tracé de courbe, mais il n'existe pas de tel composant (à part Canvas, mais c'est plutôt un outil permettant d'arriver à ce que l'on veut, non une solution toute prête). On pourrait également juste vouloir un composant non graphique mais contenant un certain nombre d'informations et de méthodes, par exemple un composant "CatInfos", contenant les informations d'un chat. Parmi ces informations, on aimerait surtout fournir au développeur QML un moyen d'utiliser l'âge et le nom du chat. Pour cela, la classe C++ devra contenir les propriétés "name" et "age", tel que défini ci-dessous :

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    class CatInfos : public QObject
    {
        Q_OBJECT
     
        // Définition de la propriété name, avec l'accesseur getName(), la méthode de modification setName et le signal notifiant un changement nameChanged
        Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged)
        // Définition de la propriété age, avec l'accesseur getAge, la méthode de modification setAge et le signal notifiant un changement ageChanged
        Q_PROPERTY(int age READ getAge WRITE setAge NOTIFY ageChanged)
     
    public:
        CatInfos() { }
     
    signals:
        void nameChanged(); // Signal permettant de notifier le QML d'un changement de la valeur de la propriété name
        void ageChanged(); // Signal permettant de notifier le QML d'un changement de la valeur de la propriété age
     
    public slots:
        void triggerBirthday() { setAge(_age + 1); } // Une méthode toute simple permettant d'augmenter l'âge de 1
     
        const QString &getName() const { return _name; } // Méthode de récupération du nom du chat
        void setName(const QString &name) { _name = name; emit nameChanged(); } // Méthode de modification du nom du chat
     
        int getAge() const { return _age; } // Méthode de récupération de l'âge du chat
        void setAge(int age) { _age = age; emit ageChanged(); } // Méthode de modification de l'âge du chat
     
    private:
        QString _name;
        int _age;
    };

    Dans le main, on doit pour étendre le QML ajouter une petite ligne :

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
     
        // On précise au QML qu'il est possible d'instancier des CatInfos, présent dans MyLib 1.0
        qmlRegisterType<CatInfos>("MyLib", 1, 0, "CatInfos");
     
        QQmlApplicationEngine engine;
        engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
     
        return app.exec();
    }

    Du côté du QML, cela donne ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    import QtQuick 2.2
    import QtQuick.Window 2.1
    import MyLib 1.0 // Import de MyLib 1.0 pour pouvoir utiliser CatInfos
     
    Window {
        visible: true
        width: 360
        height: 360
     
        CatInfos {
            id: myCat
            name: "Robert" // Modification de la propriété "name"
            age: 1 // Modification de la propriété "age"
        }
     
        Text {
            text: myCat.name + " a " + myCat.age + " an(s) !"
            anchors.centerIn: parent
        }
     
        MouseArea {
            anchors.fill: parent
            onClicked: myCat.triggerBirthday();
        }
    }
    Si on teste ça, en cliquant sur la fenêtre, cela appelle triggerBirthday() de la classe C++, qui change l'âge et pousse le QML à actualiser automatiquement le texte affiché avec le nouvel âge.
    Il me semble que dans la doc, ils parlent de communication C++/QML comme étant de la programmation QML hybride.
    Bref, voilà pour les explications. Il y a pas mal de points que j'ai abordés implicitement, notamment les propriétés, ce genre de chose. Par conséquent, n'hésitez pas à poser des questions si des points vous semblent peu clairs.

    Bonne journée,
    Louis
    N'oubliez pas de consulter la FAQ Qt ainsi que les cours et tutoriels C++/Qt !

    Dernier article : Débuter avec les Enlightenment Foundation Libraries (EFL)
    Dernières traductions : Introduction à Qt Quick - Applications modernes avec Qt et QML
    Vous cherchez un livre sur Qt 5, Qt Quick et QML ? Créer des applications avec Qt 5 - Les essentiels

  3. #3
    Futur Membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Septembre 2014
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Septembre 2014
    Messages : 3
    Points : 7
    Points
    7
    Par défaut
    Merci infiniment pour les explications.

    A propos les Q_PROPERTY j'ai trouvé ce lien qui est utile http://saildev.wordpress.com/2014/08...ing-c-and-qml/

  4. #4
    Rédacteur
    Avatar de Amnell
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2009
    Messages
    1 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 840
    Points : 5 545
    Points
    5 545
    Par défaut
    Bonjour,

    Par rapport aux Q_PROPERTY, je préfère les expliquer plus clairement, vu que cet article indique certes le comment mais pas le pourquoi. La définition d'une Q_PROPERTY permet la définition d'une propriété, par exemple avec :

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged)

    Cette ligne crée une propriété de type QString nommée "name". Cette propriété exploite la méthode getName() pour récupérer la valeur de la propriété, setName() pour la modifier et s'appuie sur le signal nameChanged() pour notifier d'un changement. Parmi les paramètres de Q_PROPERTY, seul le paramètre READ est obligatoires, le WRITE et le NOTIFY sont optionnels, tout comme d'autres paramètres additionnels moins utilisés, pouvant être trouvés dans la documentation. Sans préciser de méthode WRITE, la propriété est en lecture seule et ne peut être modifiée, ce qui explique l'intérêt du WRITE. Cependant, quel est l'intérêt du NOTIFY ?

    Voyons le fonctionnement du QML. Le QML est un langage où des composants sont déclarés et contiennent un ensemble d'assignations de la forme propriété: expression. Par exemple, un rectangle :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Rectangle {
        width: 200
        height: 200
        color: mouseArea.pressed ? "red" : "blue"
     
        MouseArea {
            id: mouseArea
            anchors.fill: parent
        }
    }
    Ainsi, width: 200 définit la propriété width (détenue par tous les composants héritant de Item QML) à la valeur constante 200. Prenons maintenant la ligne color: mouseArea.pressed ? "red" : "blue". Il s'agit d'une condition indiquant que si la propriété "pressed" de la MouseArea est à true, alors la propriété "color" doit être assignée à "red", sinon à "blue". Du point de vue fonctionnel, cela veut dire que le Rectangle est rouge si on est en train de cliquer dessus, sinon bleu. Le fait de garder la souris enfoncée dessus mènera à le laisser rouge jusqu'au relâchement, où il repassera bleu.

    Comment ça marche ? La propriété "color" a pour valeur une expression dans laquelle la propriété "pressed" de mouseArea est présente. C'est là que le signal NOTIFY entre en jeu, car le QML s'appuie dessus pour savoir quand réévaluer la propriété. Quand ce signal est émis, il va réévaluer l'expression de "color". Sans ce signal, la propriété serait figée et non réactive.

    Si on reprend le dernier exemple de mon précédent post :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
        CatInfos {
            id: myCat
            name: "Robert" // Modification de la propriété "name"
            age: 1 // Modification de la propriété "age"
        }
     
        Text {
            text: myCat.name + " a " + myCat.age + " an(s) !"
            anchors.centerIn: parent
        }
    Ici, la propriété "text" dépend des propriétés "name" et "age" du CatInfos. Lorsque l'un de leur signaux NOTIFY est émis (c'est-à-dire, quand une propriété est modifiée), l'expression est réévaluée.

    Voilà pour les explications supplémentaires concernant le pourquoi.

    Bon courage pour vos projets,
    Bonne journée,
    Louis
    N'oubliez pas de consulter la FAQ Qt ainsi que les cours et tutoriels C++/Qt !

    Dernier article : Débuter avec les Enlightenment Foundation Libraries (EFL)
    Dernières traductions : Introduction à Qt Quick - Applications modernes avec Qt et QML
    Vous cherchez un livre sur Qt 5, Qt Quick et QML ? Créer des applications avec Qt 5 - Les essentiels

  5. #5
    Futur Membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Septembre 2014
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Septembre 2014
    Messages : 3
    Points : 7
    Points
    7
    Par défaut
    Merci , c'est très gentil.
    Bonne journée!
    ----
    Tissa

  6. #6
    Candidat au Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2008
    Messages
    1
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2008
    Messages : 1
    Points : 3
    Points
    3
    Par défaut
    Je vous remercie aussi pour vos explications très claires.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. l'extraction des donnés sur les site internet avec python
    Par zakaria spearfishing dans le forum Général Python
    Réponses: 0
    Dernier message: 17/04/2013, 01h14
  2. Réponses: 0
    Dernier message: 06/04/2013, 16h27
  3. faire des requetes sur la table attributaire avec sql
    Par darkaminoo dans le forum SIG : Système d'information Géographique
    Réponses: 3
    Dernier message: 13/12/2010, 19h29
  4. Réponses: 7
    Dernier message: 20/08/2009, 19h00
  5. comment eviter des doublons sur une bd exel avec du vba
    Par INCO13 dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 24/06/2008, 23h24

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo