Le Framework Qt
Qt vs C++
Mieux que C++
Qt étend les capacités importantes de C++, pour développer avec Qt il faut avoir les connaissances requises pour développer en C++. Cependant, Qt apporte des amélioration au C++, d’abord un système de signaux et de slots qui à l’image des Listeners en Java permettent de faire communiquer des objets entre eux sans les couplés.
La bibliothèque Qt est aussi important que celle proposée pour Java, par exemple il fournit le nécessaire pour manipuler de façon plus simple qu’en C++ les chaines de caractères avec les QString, ou encore la gestion des listes avec les QList.
Qt améliore la gestion de la mémoire contrairement à C++, il faut partir du principe que tous les objets héritent de QObject comme les objets Java héritent de Object. Nous allons voir dans la partie suivante ce qu’implique cet héritage.
La gestion de la mémoire
Il n’y a pas de garbage collector en Qt contrairement à Java. Il faut faire hériter tous les objets Qt de Qobject ainsi ils gardent une référence sur un objet père. Ce mécanisme permet de construire une linked liste puisque tous les objets sont chaînées entre eux ainsi dès la destruction du père tous les objets fils sont libérés de la mémoire.
Dans la captures ci-dessus, lors de la construction du fils 1 et 3 nous leur donnons un pointeur sur leur père, alors que le fils 2 n’a qu’une référence sur le fils 1. Lors de la destruction du père à l’aide de la commande «delete», le fils 1 va être supprimé ce qui va supprimé le fils 2, enfin le fils 3 sera supprimer en dernier.
Les signaux et les slots
Les signaux et les slots sont aux C++ ce que les listeners sont au Java. Ils permettent de faire communiquer les objets entre eux sans les liés ce qui permet une réutilisation du code par la suite. En effet, un objet ne connaît pas quel objet l’appel mais il ne connait pas non plus l’objet qu’il appelle.
Un signal est une fonction émise par un objet (fonction «emit»), ce signal est associé à une fonction d’un autre objet (ou le même) ces fonctions sont appelées des slots. Nous pouvons connecter un signal à un autre et créé des cascades d’appels, on peut supprimer un signale (fonction «disconnect»). La connexion d’un signal à un slot se fait à l’aide de la commande «connect».
Dans la capture suivante nous allons voir les différents scénarios possibles.
L’objet 1 a connecté ses signaux 1 et 2 aux slots des objets 2 et 4. Ainsi lorsque le signal 1 de l’objet 1 sera émis, le slot 1 et 2 de l’objet 2 sera appelé, ceci revient à exécuter les fonctions 1 et 2 de l’objet 2. Lorsque que le signal 2 de l’objet 1 sera émis le slot 1 de l’objet 4 sera appelée. Enfin lorsque le signal 1 de l’objet 3 sera sera émis le slot 3 sera appelé.
Remarque : nous pouvons constater qu’un slot n’a pas besoin d’être connecté à un signal tout comme un signal n’a pas besoin d’être connecté à un slot pour exister.
Dans la capture ci-dessous nous allons voir comment connecter les slots et les signaux entre eux. Nous faisons le lien entre le listener en Java et les signaux en C++.
En Java nous ajoutons un listener au bouton pour que dès qu’il émet le signal «cliqué» la fonction exit soit appelée. Avec QtJambi cela revient à ajouter un objet connect à la liste clicked afin d’appliquer la fonction quit.
Avec Qt nous connectons le le signal «clicked» de l’objet bouton au slot «quit» de l’objet «app».
Ce mécanisme de signal comme nous pouvons le constater est très simple et très efficace cependant, nous n’avons pas vu comment passer des paramètres à la fonction appelée puisqu’elle n’en prenait pas.
Naturellement nous serons tentés d’écrire ceci :
connect( &a, SIGNAL(ageChange(40)), &b, SLOT(majAgePersonne(int)) );
Qt n’accepte pas que dans un connect nous passions les arguments donc cette façon n’est pas la bonne. Voici la bonne manièere de procéder :
connect( &a, SIGNAL(ageChange(int)), &b, SLOT(majAgePersonne(int)) ); emit ageChange(40);
Il faut dans la fonction «connect» déclarer les prototypes des fonctions. Ici nous spécifions que la fonction «agechange» prend un entier comme argument. Lors de l’émission de la fonction «agechange» nous spécifions le nombre à envoyer au slot «majAgePersonne».
De plus, pour permettre l’utilisation des slots et des signaux, il faut dans les fichiers d’en-têtes ajouter l’instruction «Q_OBJECT» et les instructions «slots» et «signals». Voici un exemple de déclaration :
class Personne : public QObject { Q_OBJECT public: Personne(QObject *parent=0, char *name=0 ); int agePersonne() const { return age; } public slots: void majAgePersonne( int ); signals: void ageChange( int ); private: int age; };