IUT Aix en Provence - Dépt. Informatique
Java et les Interfaces Homme-Machine
 
Henri Garreta


Java
Environnement graphique AWT


 

Cette note présente AWT (Abstract Windowing Toolkit), un ensemble de classes pour réaliser des interfaces utilisateur graphiques (GUI) dans les applications et les applets Java.

AWT respecte la portabilité des programmes Java : un programme compilé sur un système donné s'exécutera sur tout autre système supportant Java, peut-être avec un "look" différent (celui du système hôte), mais de manière fonctionnellement équivalente.

AWT possède un successeur amélioré, Swing. Optionnel dans la version 1.1, il est devenu "officiel" dans la version 1.2, dite "Java 2". Swing est plus puissant que AWT, mais on notera qu'à cause du retard que les navigateurs web ont généralement par rapport aux versions de Java, pour réaliser des applets il faut utiliser Java 1.0.2, et en particulier s'en tenir à AWT.

Table des matières

1 Composants, conteneurs, etc.
2 Composants prédéfinis
3 Gestionnaires de disposition
4 La classe Graphics
5 Evénements. Sources et auditeurs d'événements
6 Adaptateurs

1 Composants, conteneurs, etc.

Voici la hiérarchie d'héritage des principales classes permettant de réaliser des interfaces-utilisateur graphiques :

Component

L'interface graphique d'une application Java est faite de composants (classe java.awt.Component). La fenêtre principale d'une application, une boîte de dialogue, un menu, un bouton ou une case à cocher, une barre de défilement, un rectangle dans lequel une image est tracée, etc., sont des composants.

Une caractéristique essentielle d'un composant est d'être visible à l'écran. Par conséquent, une deuxième caractéristique essentielle d'un composant est de pouvoir être la cible d'actions de l'utilisateur.

La classe Component comporte de très nombreuses méthodes, en voici quelques unes :

Container

Un conteneur (classe java.awt.Container) est un composant qui peut contenir d'autres composants.

Cette classe possède de nombreuses méthodes, mais nous utiliserons surtout les trois suivantes :

Window

Une fenêtre (classe java.awt.Window) est un composant graphique de niveau supérieur (c'est-à-dire qu'elle n'est pas un morceau d'un autre composant qui l'englobe). Une fenêtre n'a pas de bord ni de barre de menus.

Si elle n'est pas une fenêtre principale, ou cadre (classe java.awt.Frame), une fenêtre est toujours la "propriété" d'une autre fenêtre. Cela organise l'ensemble des fenêtres créées par une application en une ou plusieurs arborescences, chacune ayant un cadre pour racine. La propriétaire d'une fenêtre est indiquée lors de la construction de cette dernière :

Notez qu'une fenêtre est toujours créée invisible. Il faut appeler la méthode show() pour la voir apparaître.

Parmi les méthodes des fenêtres :

Frame

Destiné à jouer le rôle de fenêtre principale d'une application, un cadre (classe java.awt.Frame) est une fenêtre (classe java.awt.Window) avec un bord et une barre de titre. Un cadre n'a pas de propriétaire, en revanche il a souvent un titre. D'où les deux constructeurs :

Un cadre peut porter une barre de menus (voir setMenuBar ci-dessous). Parmi les principales méthodes des cadres :

Dialog

Les boîtes de dialogue (classe java.awt.Dialog) sont une variété de fenêtres très utilisées dans les programmes. Contrairement aux cadres, les boîtes de dialogues sont par définition temporaires : elles apparaissent, le temps de montrer un message ou d'acquérir des données, puis elles disparaissent.

Les boîtes de dialogue peuvent être modales et non modales (option par défaut). Aussi longtemps qu'elle est affichée, une boîte de dialogue modale bloque les autres éléments visibles de l'interface de son application : il est impossible de rentrer des données dans une autre fenêtre, ou de faire passer un autre élément au premier plan. Les boîtes de dialogue non modales n'ont pas ce caractère bloquant.

Principaux constructeurs :

Quelques méthodes :

2 Composants prédéfinis

Panel

Un panneau (classe java.awt.Panel) est une surface rectangulaire à laquelle on peut attacher d'autres composants, y compris des panneaux.

Un panneau n'est pas source d'événements.

Constructeurs :

Canvas

Un canevas (classe java.awt.Canvas) est une surface rectangulaire uniformément colorée, dans laquelle l'application peut dessiner. En général pour utiliser un panneau il faut le "sous-classer" (c'est-à-dire, en définir des sous-classes) dans lesquelles on redéfinit la méthode paint(Graphics g).

Un canevas n'est pas source d'événements.

Constructeurs :

Méthodes intéressantes :

Label

Une étiquette (classe java.awt.Label) sert à placer du texte dans un conteneur. Une étiquette affiche une simple ligne de texte en lecture seule. L'application peut changer le texte, mais l'utilisateur ne peut pas l'éditer.

Une étiquette n'est pas source d'événements.

Constructeurs

Méthodes intéressantes :

Button

Un bouton (classe java.awt.Button) est un composant simple sur lequel on peut cliquer.

Un bouton génère des événements ActionEvent.

Constructeurs

Méthodes intéressantes

Checkbox

Une boîte à cocher (classe java.awt.Checkbox) est un composant possédant deux états ("coché" et "non coché"). En cliquant sur le composant on change son état.

Une case à cocher génère des événements ItemEvent.

Constructeurs :

Méthodes intéressantes :

CheckboxGroup

Un objet groupe de cases à cocher (classe java.awt.CheckboxGroup) est relié à plusieurs cases à cocher, créées par ailleurs, et fait en sorte qu'à tout instant une seule d'entre elles soit cochée : quand on coche une case, celle qui était couramment cochée se libère (comme les boutons des anciens postes radio ; les éléments d'un groupe de cases à cocher s'appellent souvent des boutons radio). Notez que l'aspect des cases à cocher change quand on les attache à un objet groupe :

Un objet CheckboxGroup ne génère pas d'événement (ce sont les boîtes à cocher qui lui sont rattachées qui génèrent leurs événements propres, à savoir des ItemEvent).

Pour construire un groupe de cases à cocher il faut d'une part construire l'objet groupe (la classe CheckboxGroup possède un constructeur sans argument) puis : soit construire les cases à cocher par des appels du constructeur

Checkbox(String label, boolean state, CheckboxGroup group)
Checkbox(String label, CheckboxGroup group, boolean state)
crée une boîte à cocher ayant l'état indiqué et associée au groupe indiqué

soit construire les cases à cocher et, avant leur affichage, les associer une par une au groupe par un appel de méthode

void setCheckboxGroup(CheckboxGroup groupe)
associe la boîte à cocher en question au groupe indiqué

List

Une liste déroulante (classe java.awt.List) affiche une collection d'items, permettant à l'utilisateur d'en choisir un ou plusieurs.

Une liste déroulante génère les événements ActionEvent et ItemEvent (voir ci-dessous des explications plus détaillées).

Ces listes sont construites vides. Une méthode (add) permet de leur ajouter des items, avant ou même après leur affichage.

Constructeurs :

List()
List(int nombreLignes)
List(int nombreLignes, boolean selectionMultiple)
crée une nouvelle liste déroulante, éventuellement ayant la hauteur (exprimée en nombre de lignes) indiquée. Par défaut, les sélections multiples ne sont pas permises. Le booléen selectionMultiple permet de changer cela.

Méthodes :

void add(String item)
void add(String item, int index)
ajoute la chaîne indiquée à la fin de la liste, ou bien à la position indiquée
void addActionListener(ActionListener auditeur)
enregistre l'auditeur d'événements "Action" indiqué.
void addItemListener(ItemListener auditeur)
enregistre l'auditeur d'événements "Item" indiqué.
void select(int index), void deselect(int index)
sélectionne/désélectionne l'item ayant le rang indiqué
String getItem(int index)
renvoie l'item ayant le rang indiqué
int getItemCount()
renvoie le nombre d'items dans la liste déroulante
String[] getItems()
renvoie les items de la liste déroulante
int getSelectedIndex()
renvoie l'indice de l'item sélectionné
int[] getSelectedIndexes()
renvoie les indices des items sélectionnés
String getSelectedItem()
renvoie l'items sélectionné
String[] getSelectedItems()
renvoie les items sélectionnés
void makeVisible(int index)
fait dérouler la liste pour rendre visible l'item ayant l'index indiqué
void remove(int position)
supprime de la liste l'item ayant l'indice indiqué
void remove(String item)
supprime de la liste la première occurrence de l'item indiqué
void removeAll()
supprime tous les items de la liste déroulante
void replaceItem(String newValue, int index)
remplace l'item ayant l'indice indiqué par la nouvelle valeur
void setMultipleMode(boolean b)
accorde ou enlève le droit de faire des sélections multiples

Comment détecte-t-on les événements dont une liste déroulante est source ?

Clics. Dans le cas où les sélections multiples ne sont pas autorisées, cliquer sur un item sélectionne celui-ci en désélectionnant, le cas échéant, l'item qui était couramment sélectionné. Si les sélections multiples sont autorisées, cliquer sur un item le sélectionne ou le désélectionne selon son état précédent.

Ces actions produisent un événement ItemEvent, que l'on peut interroger pour savoir quel est l'item qui a changé d'état : la méthode Object getItem() (classe ItemEvent) renvoie l'indice de l'item dans la liste.

Doubles-clics. Si l'on double-clique sur un item de la liste produit un événement ActionEvent, que l'on peut interroger pour savoir quel est l'item choisi par l'utilisateur : la méthode String getActionCommand (classe ActionEvent) renvoie l'item en question.

Choice

Une liste de choix (classe java.awt.Choice) est une sorte de menu apparaissant sous un bouton. L'option couramment sélectionnée est affichée comme étiquette du bouton.

Une liste de choix génère des événements ItemEvent

La classe Choice a un seul constructeur, sans argument. Les principales méthodes sont :

void add(String item)
ajoute l'item indiqué
void addItemListener(ItemListener auditeur)
enregistre l'auditeur d'événements "Item" indiqué
String getItem(int index)
renvoie l'item ayant l'indice indiqué
int getItemCount()
renvoie le nombre d'items
int getSelectedIndex()
renvoie l'indice de l'item couramment sélectionné
String getSelectedItem()
renvoie l'item couramment sélectionné
void insert(String item, int index)
insère un item à la position indiquée
void remove(int position)
supprime l'index qui se trouve à la position indiquée
void remove(String item)
supprime la première occurrence de l'item indiqué
void removeAll()
supprime tous les items
void select(int pos)
sélectionne l'item ayant l'indice indiqué
void select(String str)
sélectionne l'item indiqué

Emploi : lorsqu'un item est sélectionné, l'événement itemStateChanged se produit, avec pour argument un objet ItemEvent. La méthode getItem, appelée sur cet objet, renvoie alors l'item ayant provoqué l'événement.

Scrollbar

Une barre de défilement (classe java.awt.Scrollbar) est un curseur que l'on peut déplacer à l'intérieur d'une piste.

Une barre de défilement génère des événements AdjustmentEvent.

Constructeurs :

Scrollbar()
construit une barre de défilement verticale
Scrollbar(int orientation)
construit une barre de défilement, ayant l'orientation indiquée, parmi Scrollbar.VERTICAL et Scrollbar.HORIZONTAL.
Scrollbar(int orientation, int value, int visible, int valMin, int valMax)
construit une barre de défilement ayant l'orientation indiquée. Les autres paramètres sont :

      value : définit la position initiale du curseur
      visible : valeur représentée par la longueur du curseur
      valMin : valeur que représente le curseur lorsqu'il est à la position minimale
      valMax : valeur que représente le curseur lorsqu'il est à la position maximale

Méthodes intéressantes :

void addAdjustmentListener(AdjustmentListener l)
enregistre l'auditeur d'événements "Adjustment" indiqué
int getValue()
renvoie la valeur courante de la barre de défilement
void setMaximum(int newMaximum), void setMinimum(int newMinimum), void setOrientation(int newOrientation),
void setValue(int newValue), void setVisibleAmount(int newAmount),
void setValues(int value, int visible, int minimum, int maximum)
définit de nouvelles valeurs pour les quatre propriétés de la barre de défilement.

TextField

Un champ de texte (classe java.awt.TextField) est une zone permettant la saisie d'une ligne de texte

Une zone de texte génère les événements ActionEvent et TextEvent.

Constructeurs :

TextField()
TextField(int nombreColonnes)
TextField(String texteInitial)
TextField(String texteInitial, int nombreColonnes)
construit un nouveau champ de texte avec, le cas échéant, le nombre de colonnes et le texte initial indiqués.

Méthodes intéressantes :

void addActionListener(ActionListener auditeur)
enregistre l'auditeur d'événements "Action" indiqué
void addTextListener(TextListener auditeur)
enregistre l'auditeur d'événements "Text" indiqué
void setColumns(int columns)
redéfinit le nombre de colonnes de ce champ de texte
void setEchoChar(char c)
définit le caractère a utiliser comme "écho" des caractères tapés (saisie d'un mot secret)
void setText(String t)
redéfinit le texte présenté dans cette zone de texte

Fonctionnement. Chaque fois que l'utilisateur tape un caractère dans le champ de texte, un événement TextEvent est produit (cet événement porte très peu d'informations, et en tout cas pas le caractère qui aurait été tapé).

Lorsque l'utilisateur appuie sur la touche "Entrée", un événement ActionEvent est généré ; la méthode getActionCommand, appelée sur cet événement, renvoie comme résultat la chaîne saisie.

TextArea

Une zone de texte (classe java.awt.TextArea) permet la saisie d'un texte qui peut s'étendre sur plusieurs lignes.

Une zone de texte génère des événements TextEvent.

Constructeurs :

TextArea()
TextArea(int nombreLignes, int nombreColonnes)
TextArea(String texteInitial)
TextArea(String texteInitial, int nombreLignes, int nombreColonnes)
TextArea(String texteInitial, int nombreLignes, int nombreColonnes, int barresDéfilement)
construit une zone de texte, ayant (le cas échéant) le nombre de ligne et de colonnes indiqués, le texte initial indiqué, et les barres de défilement indiquées.
L'argument barresDéfilement, lorsqu'il est présent, est une des valeurs TextArea.SCROLLBARS_BOTH, TextArea.SCROLLBARS_VERTICAL_ONLY, TextArea.SCROLLBARS_HORIZONTAL_ONLY, et TextArea.SCROLLBARS_NONE.

Méthodes intéressantes :

 
void addTextListener(TextListener auditeur)
enregistre l'auditeur d'événements "Text" indiqué
void append(String str)
ajoute le texte indiqué au contenu courant de la zone de texte
void insert(String str, int pos)
insère le texte indiqué à la position indiquée
void replaceRange(String str, int start, int end)
remplace par le texte indiqué les caractères compris entre les positions données
void setColumns(int columns)
redéfinit le nombre de colonnes de la zone de texte
void setRows(int rows)
redéfinit le nombre de lignes de la zone de texte.

Menu

L'utilisation de menus dans les applications met en oeuvre les objets suivants

barre de menus (classe java.awt.MenuBar)
Seul un cadre (classe java.awt.Frame) peut porter une barre de menu.
Une fois construite, on attache une barre de menu à un cadre par la méthode setMenuBar(MenuBar)
menu (classe java.awt.Menu)
Un menu est généralement créé avec un titre. Par la suite on lui ajoute (méthode add) des :
items de menu (classe java.awt.MenuItem), qui peuvent être :

- construits à partir d'une chaîne de caractères (notez que la méthode add de la classe Menu prend pour argument une chaîne aussi bien qu'un MenuItem : si s est une chaîne, l'expression unMenu.add(s) est traitée comme unMenu.add(new MenuItem(s)).
- des menus (c'est pourquoi Menu est une sous-classe de MenuItem), ce qui donne lieu à des menus imbriqués ou hiérarchiques
- des objets java.awt.CheckboxMenuItem, qui se manipulent comme des boîtes à cocher (Checkbox) ; en particulier, on peut mettre ou enlever l'encoche à l'aide de la méthode setState(boolean)

Un menu génère des événements "Action".

Méthodes intéressantes des menus :

 
void addActionListener(ActionListener auditeur)
enregistre l'auditeur d'événements "Action" indiqué
MenuItem add(MenuItem item)
ajoute l'item de menu indiqué au menu en question
void add(String label)
ajoute un item de menu réduit à la chaîne de caractères donnée
void addSeparator()
ajoute un séparateur
MenuItem getItem(int index)
renvoie l'item de menu ayant l'indice indiqué
int getItemCount()
renvoie le nombre d'items du menu en question
void insert(MenuItem menuitem, int index)
insère un item de menu à la position indiquée
void insert(String label, int index)
insère un item de menu (dans le second cas réduit à une chaîne) à la position indiquée
void insertSeparator(int index)
insère un séparateur à la position indiquée
void remove(int index)
supprime l'item qui se trouve à la positon indiquée
void removeAll()
supprime tous les items du menu en question.

Lorsque l'utilisateur a fait un choix sur un menu, un événement ActionEvent est produit, pour lequel la méthode getActionCommand() renvoie le texte de l'item de menu choisi.

PopupMenu

Les menus surgissants (classe java.awt.PopupMenu), également appelés menus contextuels, ne sont pas attachés à la barre de menus et peuvent apparaître à n'importe quel endroit d'un composant, lequel n'est d'ailleurs pas obligé d'être un cadre.

On construit un menu surgissant comme on construit un menu ordinaire (le constructeur est PopupMenu()), mais on ne l'attache pas à une barre de menus. Au lieu de cela, on l'affiche, lorsque c'est nécessaire, à l'aide de la méthode

void show(Component composant, int x, int y)
fait apparaître le menu surgissant, l'angle supérieur gauche du menu se trouvant au point de coordonnées (x,y) relativement au composant indiqué.

Pour tout le reste, et notamment pour ce qui est des événements générés, les menus surgissant se comportent comme les menus ordinaires.

ScrollPane

Un panneau avec barres de défilement (classe java.awt.ScrollPane) est comme un panneau (classe java.awt.Panel) mais avec les variations suivantes :

Sans que le programmeur ait à programmer quoi que ce soit, des barres de défilement permettent de faire bouger la partie visible du composant contenu dans le panneau. Par exemple, voici un cadre (Frame) contenant un panneau avec barres de défilement (ScrollPane) contenant à son tour un canevas (Canvas) bien plus grand que lui :

Constructeurs

ScrollPane()
construction d'un panneau avec barres de défilement ; ces dernières ne seront affichées que lorsque c'est nécessaire
ScrollPane(int scrollbarDisplayPolicy)
construction d'un panneau avec barres de défilement. L'argument spécifie la politique d'affichage des barres de défilement. Il y a trois possibilités :
    ScrollPane.SCROLLBARS_ALWAYS - toujours afficher les barres, même lorsque tout le contenu est visible
    ScrollPane.SCROLLBARS_AS_NEEDED - afficher les barres lorsque c'est nécessaire
    ScrollPane.SCROLLBARS_NEVER - ne jamais afficher les barres (le défilement du contenu du panneau est provoqué par le programme)

Principales méthodes

Point getScrollPosition()
obtient les coordonnées (x,y), dans le système de coordonnées du composant, du point qui occupe la position (0,0) du panneau (c'est-à-dire l'angle supérieur gauche)
void setScrollPosition(int x, int y)
déplace la partie visible de sorte que le point (0,0) du panneau (c.-à-d. l'angle supérieur gauche) soit le point de coordonnées (x,y) dans le système de coordonnées du composant
Dimension getViewportSize()
obtient les dimensions courantes du panneau (la taille de la partie visible)
int getVScrollbarWidth(), int getHScrollbarHeight()
renvoie la largeur de la barre de défilement verticale / la hauteur de la barre de défilement horizontale.

3 Gestionnaires de disposition

Cette section n'est pas rédigée.
L'information sur les gestionnaires de disposition se trouve pour le moment dans le sujet du TP lui-même.

FlowLayout
BorderLayout
CardLayout
GridLayout
GridBagLayout

4 La classe Graphics

Un objet de la classe java.awt.Graphics est appelé contexte graphique. Un tel objet mémorise les informations et offre les méthodes nécessaires aux opérations graphiques de "bas niveau" (tirer un trait, colorier une figure simple, etc.).

Tous les composants ont un contexte graphique et peuvent donc supporter des dessins. Mais il est évident qu'on ne cherche jamais à dessiner sur des boutons, des listes de choix, des champs de texte, etc. Ces composants prennent soin de se dessiner eux mêmes, nous n'avons pas à agir sur eux à si bas niveau.

Typiquement, les contextes graphiques servent dans les applications qui effectuent des dessins sur des composants "lisses", comme des canevas (c'est le mieux, ils ont été conçus pour cela) ou des panneaux.

Il est très rare qu'on ait à construire un contexte graphique. En pratique :

Voici les principales méthodes de la classe Graphics :

5 Evénements. Sources et auditeurs d'événements

Le modèle des événements

Le modèle des événements a été considérablement modifié entre les versions 1.0 et 1.1 de AWT. Notre objet ici est la dernière version stable de Java (1.2.2, dite "Java 2").

Un événement reflète la survenue d'une circonstance qui ne résulte pas du déroulement automatique des instructions du programme en cours d'exécution, comme une action effectuée par l'utilisateur à l'aide du clavier ou de la souris.

Les points-clés du modèle des événements de Java sont les suivants :

1. Une action faite par l'utilisateur à l'aide du clavier ou de la souris s'adresse nécessairement à un composant visible à l'écran. Ce composant est appelé la source de l'événement.

2. Dans chaque composant est enregistrée une liste d'objets qui sont les auditeurs (listener) des événements dont le composant peut être la source.

3. Lors de la survenue d'un événement, le composant qui en est la source envoie un message (c'est-à-dire appelle une méthode) spécifique de l'événement à chacun de ses auditeurs enregistrés pour cette catégorie d'événements.

4. Pour qu'un objet puisse être enregistré comme auditeur d'une catégorie d'événements il faut qu'il implémente une interface associée, faite des méthodes spécifiques des événements de la catégorie en question.

Les principales interfaces d'auditeurs (c'est-à-dire les principales catégories d'événements) sont les suivantes :

Toutes ces interfaces appartiennent au paquet java.awt.event.

Exemple : si unComposant est un objet susceptible d'être la source d'événements d'une certaine catégorie XXX (avec XXX = Mouse, Action, Focus, etc.), la détection de ces événements nécessite deux choses :

1° D'une part, la définition des méthodes associées aux événements de la catégorie XXX, dans une classe qui sera une implémentation de l'interface correspondante :

class MonAuditeur implements XXXListener
{
    public void evenement_1(XXXEvent e)
    {
        actions constituant la réponse  l'événement 1
    }

    public void evenement_2(XXXEvent e)
    {
        actions constituant la réponse  l'événement 2
    }

    etc.
}

2° D'autre part, la création d'une instance de cette classe et son inscription, comme auditeur d'événements, auprès du composant en question :

...
MonAuditeur audit = new MonAuditeur();
unComposant.addXXXListener(audit);
...

MouseListener

L'interface MouseListener concerne les événements générés à l'aide de la souris, sauf les mouvements de la souris, qui sont l'objet de l'interface MouseMotionListener. Il s'agit d'événements de "bas niveau", c'est-à-dire d'actions de la souris sur un composant qui n'est pas équipé pour détecter ces actions et les traduire en des commandes évoluées (comme un bouton, menu, etc.).

Les événements de la catégorie, ou plutôt les méthodes correspondantes, sont :

void mousePressed(MouseEvent e)
appelée lorsqu'un bouton de la souris a été pressé, la souris se trouvant dans le composant en question
void mouseReleased(MouseEvent e)
appelée lorsqu'un bouton de la souris a été relâché, la souris se trouvant dans le composant en question
void mouseClicked(MouseEvent e)
appelée lorsque la souris a été cliquée (pressée puis relâchée au même endroit), la souris se trouvant dans le composant en question.
De par sa définition, cet événement est toujours précédé d'un événement mouseReleased. La réciproque n'est pas vraie : un événement mouseReleased n'est suivi d'un événement mouseClicked que si la position de la souris n'a pas changé depuis le dernier événement mousePressed.
void mouseEntered(MouseEvent e)
appelée lorsque le pointeur de la souris entre dans le composant
void mouseExited(MouseEvent e)
appelée lorsque le pointeur de la souris sort du composant

L'argument de ces méthodes est un objet MouseEvent. Les méthodes les plus intéressantes d'un tel objet sont :

auxquelles il faut ajouter une méthode héritée de InputEvent, la super-classe de MouseEvent et de KeyEvent (événements clavier) :

Ainsi, la réponse à une pression du bouton gauche (exclusivement) prendra souvent la forme suivante :

public void mousePressed(MouseEvent e) 
{
    if ((e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0)
    {
        la réaction à une pression du bouton gauche
    }  
}

MouseMotionListener

Cette interface concerne les mouvements de la souris. Lorsqu'on déplace la souris sans appuyer sur aucun bouton on dit qu'on la déplace (move), sinon on dit qu'on la traîne (drag). Cette interface comporte donc deux méthodes :

Il faut être sobre en écrivant les méthodes précédentes, car elles concernent des événements qui arrivent par trains. Selon les performances du système utilisé, un nombre élevé d'appels d'une des méthodes précédentes est généré par un seul déplacement de la souris. Il faut que la réponse soit courte pour ne pas introduire un asynchronisme désagréable.

KeyListener

Il se produit un événement clavier chaque fois qu'une touche est pressée ou relâchée. Tous les composants peuvent être source d'un tel événement (comme on l'a dit, il suffit qu'ils "aient le focus").

Cette interface se compose de trois méthodes :

ainsi que la méthode getModifiers héritée de InputEvent (voir MouseListener, précédemment expliquée).

L'événement keyTyped est assez élaboré, puisque les éventuelles touches de modification (Majuscule, Ctrl, Alt, etc.) y sont intégrées. Par exemple, la pression simultanée des touches Majuscules et A produit un seul événement keyTyped qui fournit le caractère 'A' (la touche A seule aurait fourni le caractère 'a').

Les événements keyPressed et keyReleased, au contraire, sont de bas niveau. Chacun correspond à une unique touche, et fournit un code numérique (le "code de touche virtuelle", ou VK code). En particulier, keyPressed est le seul moyen de détecter la pression d'une touche ne produisant pas de caractère (comme Majuscule, Ctrl, etc.)

L'argument de ces méthodes est un objet KeyEvent, dont les méthodes les plus intéressantes sont :

Sur la plupart des systèmes, si l'utilisateur maintient une touche pressée, un flot d'événements keyPressed et keyTyped est généré.

FocusListener

Les événements qui nous intéressent ici concernent la réception ou la cession du focus par un composant. A tout moment, un seul composant a le focus ; c'est à lui que sont adressés les événements du clavier :

ActionListener

Cette interface concerne des actions (avec la souris ou le clavier) sur un composant qui les traduit en une commande de plus haut niveau, comme un choix dans une liste ou un menu, une pression sur un bouton, etc. L'interface se compose d'une seule méthode :

L'argument de cette méthode est un objet ActionEvent, muni de la méthode

Exemple : définition d'une classe Panneau qui est le conteneur contenant, entre autres, deux boutons "Oui" et "Non" et, en même temps, l'auditrice des actions dont ces boutons sont la source :

class Panneau extends Panel implements ActionListener
{
    private Button bOui, bNon;

    public Panneau()
    {
        bOui = new Button("Oui");
        bNon = new Button("Non");
        bOui.addActionListener(this);
        bNon.addActionListener(this);
        add(bOui);
        add(bNon);
        autres composants éventuels
    }

    public void actionPerformed(ActionEvent e)
    {
        if (e.getActionCommand().equals("Oui"))
            traitement associé au bouton "Oui" 
        else if (e.getActionCommand().equals("Non"))
            traitement associé au bouton "Non" 
        else
            traitements associés  d'autres actions 
    }
}

Il faut signaler également la méthode, héritée de la super-classe EventObject :

Par exemple, la méthode actionPerformed précédente pourrait s'écrire aussi (cela fonctionne parce que les boutons ne génèrent qu'une seule action ; pour des composants plus complexes cela ne serait plus possible) :

    public void actionPerformed(ActionEvent e) 
    { 
        if (e.getSource == bOui)    
            traitement associé au bouton "Oui"  
        else if (e.getSource() == bNon)    
            traitement associé au bouton "Non"  
        else 
            traitements associés  d'autres actions 
    } 

WindowListener

Les événements que cette interface détecte sont les actions sur une fenêtre : ouverture et fermeture et, dans le cas d'un cadre (classe java.awt.Frame) les actions sur les bords du cadre et sur les éléments de la barre de titre. Ce qui donne les méthodes :

ItemListener

Il se produit un "événement d'item" lorsqu'un item est sélectionné ou déselectionné. Par item nous entendons ici un élément d'une liste déroulante (java.awt.List) ou d'une liste de choix (java.awt.Choice) ou bien une case à cocher (java.awt.Checkbox) etc.

Une seule méthode dans cette interface :

La paramètre de cette méthode est un objet ItemEvent. Parmi ses méthodes :

AdjustmentListener

Cette interface concerne les actions faites sur des barres de défilement. Une seule méthode :

En général, à la suite d'un tel événement on interroge la barre de défilement à l'aide de la méthode int getValue() (classe java.awt.Scrollbar). Dans le cas où l'on dispose de plusieurs barres de défilement, si on souhaite identifier celle qui est la source de l'événement, on peut utiliser la méthode Object getSource(), héritée de EventObject.

N.B. Le résultat rendu par getValue s'interprète à la lumière des renseignements fournis lors de la construction de la barre de défilement. Rappelons le plus complet des constructeurs :

TextListener

Les événements de cette interface notifient les modifications du texte en cours de saisie dans un champ ou une zone de texte. Une seule méthode :

void textValueChanged(TextEvent e)
appelée lorsque le texte concerné a changé.

6 Adaptateurs

Comme on l'a dit, le traitement d'une catégorie d'événements suppose l'écriture d'une classe qui est l'implémentation de l'interface correspondant à cette catégorie. Lorsque cette interface comporte plusieurs méthodes, il est assez pénible d'avoir à les écrire toutes alors que, parfois, seul un petit nombre des événements possibles, voire un seul, nous intéresse.

Les adaptateurs sont des classes qui implémentent les interfaces d'auditeurs d'événements, entièrement faites de méthodes vides. Chaque interface XXXListener possède une classe XXXAdapter correspondante. Pour écrire le traitement des événements qui nous intéressent il suffit alors donc de définir une sous classe de l'adaptateur concerné, dans laquelle seules les méthodes pertinentes sont définies.

Par exemple, proposons-nous de faire en sorte que l'utilisateur puisse mettre fin à une application à l'aide de la commande "Fermeture" du menu système ou de la case de fermeture, dans la barre de titre (cela semble la moindre des choses, toutes les applications fonctionnent ainsi !).

Cliquer dans la case de fermeture génère l'événement windowClosing de la classe WindowEvent. Sans les adaptateurs, il nous faudrait implémenter l'interface WindowListener, c'est-à-dire écrire sept méthodes alors qu'une seule aura quelque intérêt.

Avec les adaptateur, la corvée se réduit :

class FermetureApplication extends WindowAdapter
{
    public void windowClosing(WindowEvent e)
    {
        System.exit(0);
    }
}

public class MonCadre extends Frame
{
    MonCadre()
    {
        ...
        WindowListener wl = new FermetureApplication(); 
        addWindowListener(wl); 
        ...
    }
    ...
}

Classes anonymes

En fait, on peut faire encore plus simple. Ci-dessus, nous avons défini une sous-classe de WindowAdapter et redéfini une des méthodes héritées, dans le but de créer une seule instance. Dans un tel cas de figure, Java permet que l'on définisse la sous-classe dans la même expression qui crée l'instance. La sous-classe devient sans nom, mais cela n'a pas d'importance puisqu'on n'envisage pas de créer d'autres instances. Cela s'écrit :

public class MonCadre extends Frame
{
    MonCadre()
    {
        ...
        WindowListener wl = new WindowAdapter() 
        {
            public void windowClosing(WindowEvent e)
            {
                System.exit(0);
            }
        }; 
        addWindowListener(wl);
        ...
    }
    ...
}

N.B. Si on aime les écritures compactes, on peut se passer de la variable wl :