Interfaces Graphiques avec Java

TD 1

Composants simples: fenêtres, paneaux, boutons, labels. Dessins de textes, de traits, de formes et d'images. Évènements de fenêtres, de boutons, de souris et du clavier. Pluggable look and feel (plaf).


Exercice 1 - Une simple Frame

  1. Écrire une classe SimpleFrame permettant d'afficher une fenêtre. Elle pourra hériter, dans un premier temps, de la classe javax.swing.JFrame. On lui donnera simplement un titre et une taille initiale avant de l'afficher (show()).
  2. Ajouter à cette fenêtre un label, composant de la classe JLabel, représentant une étiquette (un texte court). Le conteneur d'une frame dans lequel on peut ajouter quelquechose est récupéré par la méthode getContentPane().
  3. Remplacer l'ajout de label par l'ajout d'un bouton "OK", de la classe JButton. Que se passe-t-il le bouton est ajouté en plus du label, au lieu de le remplacer?
D'une manière générale, on n'ajoute pas directement des composants dans le contentPane d'une fenêtre JFrame. On préfère spécifier l'ensemble des composants désirés dans un paneau de la classe JPanel, puis ajouter le paneau dans le contentPane de la fenêtre JFrame.

Modifier l'exemple SimpleFrame en ce sens.


Exercice 2 - Un peu de dessin

  1. Écrire une classe SimpleDessin, héritant de JFrame. On positionnera, dans le contentPane de cette frame, une instance d'une classe DessinPanel, héritant de JPanel. Les dessins seront alors spécifiés en redéfinissant la méthode paintComponent() dans DessinPanel.
  2. Spécifier, via cette méthode, le dessin à différents endroits de la fenêtre: où les méthodes entre parenthèses doivent être appelées sur l'objet graphique (java.awt.Graphics) argument de la méthode paintComponent(). Comment épaissir le trait de la ligne bleue?
  3. Positionner la couleur de fond du dessin comme étant jaune.

Exercice 3 - Dessiner des images

On veut maintenant dessiner une image (gif ou jpeg, par exemple) accessible dans le répertoire courant.

  1. Récupérer l'objet Toolkit courant par la méthode statique getDefaultToolkit() de la classe java.awt.Toolkit).
  2. Récupérer cette image sous la forme d'un objet de la classe Image (utiliser pour cela la méthode getImage() qui accepte un nom de fichier ou un objet URL.
  3. Dessiner cette image dans la fenêtre grâce à la méthode drawImage().
  4. Faire de même avec une image récupérée à partir d'un URL (par exemple, new URL("http://www-igm.univ-mlv.fr/~duris/logo.gif")).

Exercice 4 - Les écouteurs d'évènements des fenêtres

Dans l'ensemble des exemples précédents, que se passe-t-il lorsqu'on ferme la fenêtre?
  1. Pour terminer proprement l'application lorsqu'on ferme la fenêtre, faire implanter à la frame la methode windowClosing() de l'interface java.awt.event.WindowListener. Afin d'éviter de donner un code vide pour toutes les autres méthodes de WindowListener, utiliser un WindowAdapter.
  2. De la même manière, faire en sorte que la couleur de fond de la fenêtre soit verte lorsqu'elle est active et rouge lorsqu'elle est inactive.

Exercice 5 - Associer des actions aux boutons

Créer une classe ButtonPanel, qui hérite de JPanel et dont une instance sera intégrée dans le contentPane d'une JFrame visualisant l'ensemble. La classe ButtonPanel contient:
  1. Un bouton "Test" qui, lorsqu'il reçoit un clic, affiche "Test clic" dans la fenêtre de contrôle (xterm). Pour cela, il faut créer le bouton, puis lui ajouter, par la méthode addActionListener() un écouteur implantant l'interface ActionListener, dont la méthode actionPerformed() effectue l'affichage dans la fenêtre de contrôle.
  2. Trois boutons, "Rouge", "Vert" et "Bleu", qui permettent lorsqu'ils sont utilisés de changer la couleur de fond.

Exercice 6 - Changer de look & feel

Le laf (look and feel) utilisé dans les interfaces graphiques de Swing est modifiable dynamiquement (pluggable). Trois plaf existent actuellement: ceux de Motif et de Windows plus celui de Swing utilisé par défaut, appelé Metal.

Créer, comme pour le dernier exercice, trois boutons "Motif", "Windows"et "Metal" permettant de changer dynamiquement le Look and Feel. La méthode setLookAndFeel() de la classe javax.swing.UIManager permet de positionner un plaf particulier, représenté par une String, dont les valeurs peuvent être les suivantes:

Une fois positionné, le plaf est pris en compte par un appel à la méthode statique updateComponentTreeUI() de la classe SwingUtilities.


Exercice 7 - Créer et détruire dynamiquement des boutons

O souhaite écrire un programme qui affiche une fenêtre dans laquelle des boutons vont dynamiquement apparaître ou disparaître. Plus précisément, écrire successivement du code permettant le comportement suivant:
  1. Initialement, un seul bouton "New" est présent. Un clic sur ce bouton fait apparaître un nouveau bouton étiqueté avec un texte contenant un numéro d'ordre de création.
  2. Ensuite, un clic sur l'un de ces boutons doit le faire disparaître.
  3. Enfin, un troisième type de bouton, "Reset", permet lorsqu'il subit un clic de faire disparaître tous les boutons crées, ne laissant que les deux boutons initiaux "New" et "Reset".
Ajouter des bulles d'aide contextuelles (ToolTip) aux trois types de boutons. Pour cela, utiliser la méthode setToolTipText.

Exercice 8 - Utiliser les évènements du clavier

On veut ici écrire un petit programme de dessin du style télécran qui, en fonction des touches de flèches du clavier utilisées, dessine un trait continu vers le haut, le bas, la gauche ou la droite. Pour cela, il faut:
  1. Faire implanter, au JPanel dans lequel on veut dessiner, l'interface java.awt.event.KeyListener. La méthode keyPressed() de cette interface permet de spécifier le comportement lors de l'enfoncement d'une touche du clavier et la méthode keyReleased() le comportement lors du relachement d'une touche. La méthode keyTyped() correspond aux deux actions successives sur une touche.
  2. On pourra considérer que le dessin se fait le tracé d'une ligne entre les coordonnées de deux points, celui de la position courante et celui de la position calculée en fonction de la touche enfoncée, qui devient alors la nouvelle position courante. Il faut donc donner des coordonnées pour le point de départ.
  3. On peut spécifier, dans un premier temps, l'action à effectuer lors des pressions sur les touches de flèches, en comparant le code de la touche pressée (obtenu par la méthode getKeyCode() sur l'évènement de type KeyEvent en paramètre de la méthode keyPressed()) avec les constantes de touches virtuelles représentant les touches concernées, c'est-à-dire KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT, KeyEvent.VK_UP et KeyEvent.VK_DOWN.
  4. Incorporer ensuite au code le fait que l'appui simultané sur la touche Shift produit un facteur d'accélération du déplacement. Les touches de modifications, comme Shift, Control, etc. peuvent être testées en appliquant un masque (InputEvent.SHIFT_MASK) sur l'entier (fourni par la méthode getModifiers() sur un KeyEvent) représentant les modificateurs de la touche pressée.

Etienne.Duris[at]univ-mlv.fr - © Université de Marne-La-Vallée - Janvier 2000 - http://www-igm.univ-mlv.fr/~duris