Penser en Java 2nde édition | - | Sommaire | Préface | Avant-propos | Chapitre : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | Annexe : A B C D | Tables des matières | - | Thinking in Java |
Dans l'exemple suivant, toute l'intelligence concernant le dessin est contenue dans la classe SineDraw; la classe SineWave configure simplement le programme et le curseur. Dans SineDraw, la méthode setCycles() fournit un moyen pour permettre à un autre objet (le curseur dans ce cas) de contrôler le nombre de cycles.
Tous les membres de données et tableaux sont utilisés dans le calcul des points du sinus : cycles indique le nombre de périodes complètes de sinus désiré, points contient le nombre total de points qui sera tracé, sines contient les valeurs de la fonction sinus, et pts contient les coordonnées y des points qui seront tracés sur le JPanel. La méthode setCycles() construit le tableau selon le nombre de points nécessaires et remplit le tableau sines de valeurs. En appelant repaint(), setCycles force l'appel de paintComponent() , afin que le reste des calculs et le dessin aient lieu.
La première chose à faire lorsqu'on redéfinit paintComponent() est d'appeler la version de base de la méthode. Ensuite on peut faire ce que l'on veut; normalement cela signifie utiliser les méthodes de Graphics qu'on peut trouver dans la documentation de java.awt.Graphics (dans la documentation HTML de java.sun.com) pour dessiner et peindre des pixels sur le JPanel. On peut voir ici que la plupart du code concerne l'exécution des calculs, les deux seules méthodes qui manipulent effectivement l'écran sont setColor() et drawLine(). Vous aurez probablement la même sensation lorsque vous créerez votre propre programme d'affichage de données graphiques : vous passerez la plus grande partie du temps à déterminer ce qu'il faut dessiner, mais le dessin en lui-même sera assez simple.
Lorsque j'ai créé ce programme, j'ai passé le plus gros de mon temps à obtenir la courbe du sinus à afficher. Ceci fait, j'ai pensé que ce serait bien de pouvoir modifier dynamiquement le nombre de cycles. Mes expériences de programmation de ce genre de choses dans d'autres langages me rendaient un peu réticent, mais cette partie se révéla la partie la plus facile du projet. J'ai créé un JSlider (les arguments sont respectivement la valeur de gauche du JSlider, la valeur de droite, et la valeur initiale, mais il existe d'autres constructeurs) et je l'ai déposé dans le JApplet. Ensuite j'ai regardé dans la documentation HTML et j'ai vu que le seul listener était le addChangeListener, qui était déclenché chaque fois que le curseur était déplacé suffisamment pour produire une nouvelle valeur. La seule méthode pour cela était évidemment appelée stateChanged(), qui fournit un objet ChangeEvent, de manière à pouvoir rechercher la source de la modification et obtenir la nouvelle valeur.En appelant setCycles() des objets sines, la nouvelle valeur est prise en compte et le JPanel est redessiné.
En général, on verra que la plupart des problèmes Swing peuvent être résolus en suivant un processus semblable, et on verra qu'il est en général assez simple, même si on n'a pas utilisé auparavant un composant donné.
Si le problème est plus compliqué, il y a d'autres solutions plus sophistiquées, par exemple les composants JavaBeans de fournisseurs tiers, et l'API Java 2D. Ces solutions sortent du cadre de ce livre, mais vous devriez les prendre en considération si votre code de dessin devient trop coûteux.
Une boîte de dialogue est une fenêtre qui est issue d'une autre fenêtre. Son but est de traiter un problème spécifique sans encombrer la fenêtre d'origine avec ces détails. Les boîtes de dialogue sont fortement utilisées dans les environnements de programmation à fenêtres, mais moins fréquemment utilisées dans les applets.
Pour créer une boîte de dialogue, il faut hériter de JDialog, qui est simplement une sorte de Window, comme les JFrames. Un JDialog possède un layout manager (qui est par défaut le BorderLayout) auquel on ajoute des listeners d'événements pour traiter ceux-ci. Il y a une différence importante : on ne veut pas fermer l'application lors de l'appel de windowClosing(). Au lieu de cela, on libère les ressources utilisées par la fenêtre de dialogue en appelant dispose(). Voici un exemple très simple :
Une fois le JDialog créé, la méthode show() doit être appelée pour l'afficher et l'activer. Pour que le dialogue se ferme, il faut appeler dispose().
On remarquera que tout ce qui sort d'une applet, y compris les boîtes de dialogue, n'est pas digne de confiance. C'est à dire qu'on obtient un avertissement dans la fenêtre qui apparaît. Ceci est dû au fait qu'en théorie il serait possible de tromper l'utilisateur et lui faire croire qu'il a à faire avec une de ses applications normales et de le faire taper son numéro de carte de crédit, qui partirait alors sur le Web. Une applet est toujours attachée à une page Web et visible dans un navigateur, tandis qu'une boîte de dialogue est détachée, et tout ceci est donc possible en théorie. Le résultat est qu'il n'est pas fréquent de voir une applet qui utilise une boîte de dialogue.
L'exemple suivant est plus complexe; la boîte de dialogue est composée d'une grille (en utilisant GridLayout) d'un type de bouton particulier qui est défini ici comme la classe ToeButton. Ce bouton dessine un cadre autour de lui et, selon son état, un blanc, un x ou un o au milieu. Il démarre en blanc, et ensuite, selon à qui c'est le tour, se modifie en x ou en o. Cependant, il transformera le x en o et vice versa lorsqu'on clique sur le bouton (ceci rend le principe du tic-tac-toe seulement un peu plus ennuyeux qu'il ne l'est déjà). De plus, la boîte de dialogue peut être définie avec un nombre quelconque de rangées et de colonnes dans la fenêtre principale de l'application.
Comme les statics peuvent être uniquement au niveau le plus extérieur de la classe, les classes internes ne peuvent pas avoir de données static ni de classes internes static.
La méthode paintComponent() dessine le carré autour du panneau, et le x ou le o. C'est rempli de calculs fastidieux, mais c'est direct.
Les clics de souris sont capturés par le MouseListener, qui vérifie d'abord si le panneau a déjà quelque chose d'écrit sur lui. Si ce n'est pas le cas, on recherche la fenêtre parente pour déterminer à qui est le tour, et on positionne l'état du ToeButton en conséquence. Le ToeButton retrouve le parent par le mécanisme de la classe interne, et passe au tour suivant. Si le bouton affiche déjà un x ou un o, son affichage est inversé. On peut voir dans ces calculs l'usage pratique du if-else ternaire décrit au Chapitre 3. On repeint le ToeButton chaque fois qu'il change d'état.
Le constructeur de ToeDialog est assez simple : il ajoute à un GridLayout autant de boutons que demandé, puis redimensionne chaque bouton à 50 pixels.
TicTacToe installe l'ensemble de l'application par la création de JTextFields (pour entrer le nombre de rangées et colonnes de la grille de boutons) et le bouton «go» avec son ActionListener. Lorsqu'on appuie sur le bouton, les données dans les JTextFields doivent être récupérées et, puisqu'elles sont au format String, transformées en ints en utilisant la méthode statique Integer.parseInt().
Certains systèmes d'exploitation ont des boîtes de dialogue standard pour gérer certaines choses telles que les fontes, les couleurs, les imprimantes, et cetera. En tout cas, pratiquement tous les systèmes d'exploitation graphiques fournissent les moyens d'ouvrir et de sauver les fichiers, et le JFileChooser de Java les encapsule pour une utilisation facile.
L'application suivante utilise deux sortes de dialogues JFileChooser, un pour l'ouverture et un pour la sauvegarde. La plupart du code devrait maintenant être familière, et toute la partie intéressante se trouve dans les action listeners pour les différents clics de boutons :