IX. Une chose mène à une autre▲
- tutorial/t7/lcdrange.cpp
- tutorial/t7/lcdrange.h
- tutorial/t7/main.cpp
Cet exemple montre comment créer des widgets personnalisés avec des signaux et des slots, et comment les connecter d'une manière plus complexe. Pour la première fois, le code source est divisé en plusieurs fichiers que nous avons placés dans le répertoire exemples/tutorial/t7.
IX-A. Analyse du code ligne par ligne ▲
IX-A-1. t7/lcdrange.h▲
#ifndef LCDRANGE_H
#define LCDRANGE_H
Ces deux lignes de code, combinées avec le #endif placé en fin de fichier, correspondent à une construction standard du langage C++ qui évite toute erreur dans le cas où le fichier en-tête viendrait à être inclus plusieurs fois. Si vous ne pratiquez pas encore cette syntaxe, prenez cette bonne habitude en tant que développeur.
#include
<QWidget>
QWidget se trouve inclus du fait que notre LCDRange hérite de QWidget. On doit toujours inclure l'en-tête de la classe parente ; dans les tutoriels précédents, on a un peu « triché » en incluant le fichier QWidget d'une manière indirecte, via d'autres fichiers en-tête.
class
QSlider
;
Ceci est une autre astuce classique, moins utilisée cependant que la précédente. On n'a pas besoin de QSlider dans l'interface de la classe, on l'utilisera dans l'implémentation. On utilise uniquement la déclaration de la classe QSlider dans le fichier en-tête, et on utilise le fichier en-tête de QSlider dans le fichier .cpp.
Ceci accélère la compilation des grands projets, car le compilateur passe la plus grande partie de son temps à parcourir les fichiers en-tête ; ce n'est pas le cas avec le code actuel. Cette seule astuce augmente la vitesse de compilation d'au moins un facteur deux.
class
LCDRange : public
QWidget
{
Q_OBJECT
public
:
LCDRange(QWidget
*
parent =
0
);
Noter Q_OBJECT. Cette macro doit être déclarée dans toutes les classes contenant des signaux et des slots. Si vous êtes curieux, sachez qu'elle définit toutes les fonctions implémentées dans le fichier métaobjet.
int
value() const
;
public
slots
:
void
setValue(int
value);
signals
:
void
valueChanged(int
newValue);
Ces trois membres créent une interface entre ce widget et d'autres composants du programme. Jusqu'à présent, LCDRange ne contenait aucune API.
value() est une méthode publique permettant d'accéder à la valeur de LCDRange ; setValue() est notre premier slot et valueChanged() est notre premier signal personnalisé.
Les slots doivent être implémentés comme d'habitude (un slot est aussi une fonction membre C++). Les signaux sont automatiquement implémentés dans le fichier métaobjet. Les signaux obéissent aux règles C++ des fonctions membres protégées (c'est-à-dire qu'ils ne peuvent être émis que par la classe où ils sont déclarés et par les classes dérivées de cette dernière).
Le signal valueChanged() est utilisé quand la valeur de LCDRange change.
IX-A-2. t7/lcdrange.cpp▲
LCDRange *
previousRange =
0
;
for
(int
row =
0
; row <
3
; ++
row) {
for
(int
column =
0
; column <
3
; ++
column) {
LCDRange *
lcdRange =
new
LCDRange;
grid->
addWidget(lcdRange, row, column);
if
(previousRange)
connect
(lcdRange, SIGNAL
(valueChanged(int
)),
previousRange, SLOT
(setValue(int
)));
previousRange =
lcdRange;
}
}
Tout le main.cpp a été copié du chapitre précédent, à l'exception du constructeur de MyWidget. Quand on crée les neuf objets LCDRange, on les connecte avec le mécanisme des signaux et des slots. Chacun possède son propre signal valueChanged() connecté au slot setValue() du précédent. Le fait que LCDRange émette le signal valueChanged() au changement de sa valeur engendre un enchaînement de signaux et de slots.
IX-B. Compiler l'application▲
Créer un Makefile pour une application multifichier ne diffère pas de la création d'un Makefile pour une application à fichier unique. Si vous avez sauvegardé vos fichiers dans un seul répertoire, tout ce qui vous reste à faire est de taper dans un prompt :
qmake -project
qmake
La première commande donne l'ordre à qmake de créer un fichier .pro. La seconde lui ordonne de créer un Makefile (spécifique à la plateforme) basé sur le fichier projet. Vous devriez maintenant pouvoir exécuter make (ou nmake si vous utilisez Visual Studio) pour construire l'application.
IX-C. Exécuter l'application▲
Au lancement, le programme a la même apparence que dans le chapitre précédent. Essayez de manipuler le curseur situé dans le coin inférieur droit.
IX-D. Exercices▲
Utilisez le curseur du coin inférieur droit pour régler tous les LCD sur 50. Ensuite, réglez les six premiers sur 30 en cliquant sur le curseur de la ligne inférieure. Maintenant, utilisez le curseur situé à gauche du dernier curseur manipulé pour remettre les cinq premiers LCD à 50.
Maintenant, cliquez sur la gauche du bouton du slider inférieur droit. Que se passe-t-il ? Pour quelle raison ce comportement est-il normal ?