 |
5. GRAPHISME AVEC L'AWT |
Il existe actuellement deux bibliothèques standards en Java pour le graphisme, l'AWT
(Abstract Window Toolkit) et Swing. La seconde est plus récente, mais plus
délicate à manipuler. Nous proposons donc de présenter plutôt des
composants de l'AWT qui se trouvent dans le package java.awt.
La première chose à faire dans toute interface graphique est de fournir une ou
plusieurs fenêtres qui vont accueillir les composants graphiques de l'application. Nous nous
intéressons simplement ici à l'ouverture d'une fenêtre dans laquelle on peut
dessiner simplement. Mais il faut savoir que l'AWT propose une hiérarchie de nombreux
composants graphiques comme des boutons, des menus déroulants..., tous héritant de la
super-classe Component. L'exemple qui suit ouvre deux fenêtres, chacune contenant
un composant simple, de la classe Panel, qui prend tout l'espace de la fenêtre,
et dans lequel est affiché un rectangle.
import java.awt.*;
public class Fenetre extends Frame {
protected Panneau panneau;
public Fenetre(String titre) {
super(titre); // Appelle le constructeur de la super-classe.
panneau=new Panneau(); // Crée un panneau.
setLayout(new BorderLayout()); // Crée le gestionnaire de
placement.
add(panneau,BorderLayout.CENTER); // Place le panneau dans la
fenêtre.
pack(); // Dimensionne la fenêtre et ses composants.
setResizable(false); // Indique que la fenêtre n'est pas
redimensionnable.
setVisible(true); // Affiche la fenêtre.
}
public Dimension getPreferredSize() // Utilisée par la méthode
pack pour
{ return (new Dimension(200,200)); } // connaître la taille de la
fenêtre.
public static void main(String args[]) {
new Fenetre("Fenetre 1");
new Fenetre("Fenetre 2");
}
}
class Panneau extends Panel {
public Panneau() { super(); }
public void paint(Graphics g) {
super.paint(g);
g.drawRect(10,10,getWidth()-20,getHeight()-20);
}
}
La classe Fenetre hérite de Frame, dont le constructeur
reçoit une chaîne de caractères qui est le titre de la fenêtre. Dans le
constructeur de Fenetre, un composant Panel est créé et
positionné sur la fenêtre. La méthode setLayout permet de
spécifier quel est le gestionnaire chargé de positionner les composants sur la
fenêtre. Nous utilisons ici un gestionnaire de la classe BorderLayout, qui
permet de positionner les composants de manière relative, mais il en existe d'autres avec
des politiques de placement différentes. La méthode add ajoute le
composant Panel dans la fenêtre, en demandant de le centrer (grâce
à BorderLayout.CENTER). Le gestionnaire le positionnera ensuite
automatiquement, mais étant le seul composant, il occupera tout l'espace de la
fenêtre. La méthode pack redimensionne la fenêtre et les composants
qu'elle contient, et pour connaître la taille de la fenêtre, elle interroge sa
méthode getPreferredSize. Les méthodes setResizeable et
setVisible indiquent respectivement que la fenêtre n'est pas redimensionnable et
qu'elle est visible.
La méthode paint dessine un rectangle dans le composant Panel,
mais cette opération sera détaillée plus tard.
Notons simplement que la méthode
paint est appelée chaque fois que l'on a besoin d'afficher le composant (i.e.
la première fois qu'il apparaît à l'écran, lorsqu'une fenêtre qui
cachait le composant le dévoile à nouveau...). Il est d'usage de mettre dans cette
méthode le code correspondant à l'affichage du composant.
En exécutant l'exemple précédent, on s'aperçoit qu'il est impossible
de fermer les fenêtres, simplement parce que l'événement engendré par le
clic de la souris sur le bouton de fermeture de la fenêtre n'a pas été
récupéré et traité par le programme. Pour cela, il faut mettre en place
des objets, les listeners, chargés de cette écoute. Ils appartiennent à
la classe (ou plus exactement à l'interface) EventListener. Par exemple,
lorsque l'événement de fermeture de la fenêtre est levé, la
méthode windowClosing du listener attaché à la
fenêtre est exécutée.
Pour traiter cet événement, il faut donc créer un listener de
fenêtre, de la classe WindowAdapter, et redéfinir sa méthode
windowClosing. Il suffit ensuite de le rattacher à la fenêtre par la
méthode addWindowListener. L'exemple précédent est
complété pour que la fermeture des fenêtres soit possible. L'une des deux
fenêtres, la fenêtre maîtresse terminera l'application lorsqu'elle se fermera,
alors que l'autre, la fenêtre esclave, ne stoppera pas l'application à sa fermeture.
import java.awt.*;
import java.awt.event.*;
public class Fenetre extends Frame {
protected boolean maitre;
protected Panneau panneau;
protected class EvenementFenetre extends WindowAdapter {
public void windowClosing(WindowEvent e) {
dispose(); // Ferme la fenêtre.
if (maitre) System.exit(0);
}
}
public Fenetre(String titre,boolean m) {
super(titre);
panneau=new Panneau();
maitre=m;
setLayout(new BorderLayout());
add(panneau,BorderLayout.CENTER);
addWindowListener(new EvenementFenetre());
pack();
setResizable(false);
setVisible(true);
}
public Dimension getPreferredSize()
{ return (new Dimension(200,200)); }
public static void main(String args[]) {
new Fenetre("Fenetre maitresse",true);
new Fenetre("Fenetre esclave",false);
}
}
Toutes les classes permettant la gestion des événements des composants
graphiques se trouvent dans le package java.awt.event.
Pour gérer les événements du clavier, le mécanisme est identique
à celui des événements d'une fenêtre. La différence ici est la
classe du listener, qui est KeyAdapter, et donc les méthodes à
redéfinir. Le plus simple pour introduire tous les événements importants est un
exemple. Voici un listener pour les événements du clavier.
protected class EvenementClavier extends KeyAdapter {
public void keyPressed(KeyEvent e) {
if (e.getKeyChar()==KeyEvent.CHAR_UNDEFINED)
System.out.println(getTitle()+", touche de controle "
+e.getKeyCode()+"
enfoncee...");
else
System.out.println(getTitle()+", touche '"
+e.getKeyChar()+"'
enfoncee...");
}
public void keyReleased(KeyEvent e) {
if (e.getKeyChar()==KeyEvent.CHAR_UNDEFINED)
System.out.println(getTitle()+", touche de controle "
+e.getKeyCode()+"
relachee...");
else
System.out.println(getTitle()+", touche '"
+e.getKeyChar()+"'
relachee...");
}
}
Le listener capture entre autres deux types d'événements: "une touche
est enfoncée" (la méthode keyPressed est appelée) et
"une touche est relâchée" (la méthode keyReleased est
appelée). Les méthodes appelées lors d'un événement du clavier
reçoivent un paramètre de la classe KeyEvent. Deux méthodes
getKeyChar et getKeyCode de cet objet permettent respectivement de
récupérer soit le caractère associé à la touche impliquée
dans l'événement, soit directement son code. La méthode
getKeyChar retourne KeyEvent.CHAR_UNDEFINED si la touche n'a pas de
caractère associé. La méthode getKeyCode retourne un entier, mais
des constantes symboliques sont fournies pour déterminer plus facilement quelle touche a
été appuyée ou relâchée. Voici un extrait de ces codes.
| Constante |
Touche |
VK_LEFT |
Flèche gauche |
VK_RIGHT |
Flèche droite |
VK_UP |
Flèche haut |
VK_DOWN |
Flèche bas |
VK_PAGE_UP |
Flèche page haut |
VK_PAGE_DOWN |
Flèche page bas |
VK_TAB |
Tabulation |
VK_BACK_SPACE |
Backspace |
VK_SHIFT |
Shift |
VK_CONTROL |
Ctrl |
VK_ALT |
Alt |
VK_ALT_GRAPH |
Alt Gr |
Il ne faut pas oublier de rattacher le listener de clavier à la fenêtre,
pour cela il faut rajouter la ligne suivante dans le constructeur de la fenêtre, de
manière semblable au listener de fenêtre.
addKeyListener(new EvenementClavier());
Pour gérer les événements de la souris, le mécanisme est identique
aux autres types d'événements. La classe du listener à dériver dans
ce cas est MouseAdapter. Voici un exemple de listener pour les
événements de la souris. Ce listener est placé sur le composant
Panel. C'est sur lui que l'on clique, il reçoit donc les
événements de la souris.
class Panneau extends Panel {
protected class EvenementSouris extends MouseAdapter {
public void mousePressed(MouseEvent e)
{ getGraphics().drawRect(e.getX(),e.getY(),1,1); }
public void mouseReleased(MouseEvent e)
{ System.out.println("Souris relachee..."); }
}
public Panneau() {
super();
addMouseListener(new EvenementSouris());
}
public boolean isFocusTraversable() { return false; }
public void paint(Graphics g) {
super.paint(g);
g.drawRect(10,10,getWidth()-20,getHeight()-20);
}
}
Lorsque l'on clique sur le composant Panel, le focus du clavier lui est
attribué par défaut. Ce qui signifie que le listener de clavier attaché
à la fenêtre ne reçoit plus les événements du clavier. Pour
éviter cette perte de focus, il suffit d'indiquer que le composant Panel ne
désire pas obtenir le focus, en redéfinissant la méthode
isFocusTraversable pour qu'elle retourne false.
Il est possible de dessiner dans la plupart des composants héritant de la classe
Component, mais cela ne se fait pas directement, il faut utiliser un
intermédiaire, un contexte graphique, un objet de la classe Graphics.
Pour l'obtenir, il suffit d'appeler la méthode getGraphics du composant, elle
retourne alors un objet de cette classe (cf. la méthode mousePressed de
l'exemple précédent). Mais certaines méthodes, comme paint,
reçoivent directement cet objet en paramètre (cf. l'exemple précédent).
Un contexte graphique possède des méthodes pour afficher des formes dans
le composant qu'il référence. Le tableau suivant récapitule les plus importantes.
| Méthode |
Description |
drawArc(x,y,l,h,a1,a2) |
Trace un arc de cercle dans le rectangle de coin
(x;y), de largeur l et de hauteur h. L'arc
commence à l'angle a1 et se termine à l'angle a2,
exprimés en degré. |
fillArc(x,y,l,h,a1,a2) |
La même chose avec une forme pleine. |
drawLine(x1,y1,x2,y2) |
Trace une ligne entre les coordonnées
(x1;y1) et (x2;y2). |
drawRect(x,y,l,h) |
Trace un rectangle de coin (x;y), de largeur
l et de hauteur h. |
fillRect(x,y,l,h) |
La même chose avec une forme pleine. |
drawString(s,x,y) |
Dessine la chaîne de caractères s aux
coordonnées (x;y). |
Il est possible de spécifier la couleur des formes dessinées, pour cela il faut
utiliser la méthode setColor du contexte graphique. Elle attend en
paramètre une couleur qui est un objet de la classe Color. Des couleurs sont
prédéfinies dans la classe, par exemple Color.red,
Color.green... Mais il est possible de définir ses propres couleurs en
indiquant leur code RGB (Red / Green / Blue), c'est-à-dire leur niveau de rouge, de
vert et de bleu, ces valeurs étant des flottants entre 0 et 1. L'exemple suivant dessine un
rectangle orange dans le contexte graphique du composant courant.
Graphics g = getGraphics();
g.setColor(new Color((float)1.0,(float)0.5,(float)0.0));
g.fillRect(50,50,100,100);
| |
| |
| Copyright (c) 1999-2016 - Bruno Bachelet - bruno@nawouak.net -
http://www.nawouak.net |
| La permission est accordée de copier, distribuer et/ou modifier ce document
sous les termes de la licence GNU Free Documentation License, Version 1.1 ou toute
version ultérieure publiée par la fondation Free Software Foundation. Voir
cette licence pour plus de détails (http://www.gnu.org). |
|
|
|