X - AWT

 

Dans ce chapitre nous allons présenter l'API AWT (Abstract Window Toolkit) permettant de créer des interfaces graphiques en Java. Les notions introduites dans ce chapitre nous permettrons d'aborder la programmation des appets, dans le prochain chapitre.

 

1. Concepts de base

Dans ce paragraphe, nous allons présenter ou rappeler quelques concepts de base concernant la conception d'interfaces utilisateur.

On distingue généralement deux phases :

Un événement se produit sur intervention de l'utilisateur. Il peut s'agir d'un clic de souris, du déplacement de celle-ci dans une zone ou encore de l'affichage d'une fenêtre ou portion de fenêtre précédemment masquée, impliquant ainsi la nécessité d'un rafraîchissement de l'affichage.

L'AWT, Abstract Window Toolkit, permet de construire une interface, en positionnant des composants dans des containers chargés de les disposer d'une certaine façon et d'y associer des gestionnaires d'événements ayant pour but d'effectuer certaines opérations sur occurrence d'un événement.

Nous allons maintenant détailler les deux phases précédemment citées, en décrivant ce que propose l'AWT.

 

2. Les composants

Un composant est tout simplement un élément que l'on peut inclure dans une interface graphique. Les classes décrivant ces composants héritent d'une super-classe appelée Component, de même que toutes les classes (appartenant au package java.awt) que nous verrons dans ce chapitre.

Voici la liste des principaux composants proposés par l'AWT :

Nous verrons un peu plus loin des exemples qui nous permettrons de présenter les principales méthodes associées à ces objets. Vous constaterez par ailleurs que le nombre de composants proposés par l'AWT est relativement faible, ceci étant dû au fait que pour des raisons de portabilité, il n'était pas possible de proposer des éléments plus complexes ou sophistiqués.

 

3. Les containers

Un container est un composant qui a pour rôle de gérer la disposition d'autres composants. Cette disposition s'appelle le layout. Il est important de noter qu'un container est également un composant (puisque toutes les classes considérées ici héritent de la même classe Component), si bien qu'un container peut en contenir d'autres. Avant de lister les différents types de layout, nous allons voir quelques méthodes fondamentales de la classe Container.

La première opération que l'on désire effectuer est d'ajouter un composant à un container. Pour ce faire, on utilise la méthode add(). Cette méthode prend en argument un composant et demande au container de le positionner suivant son layout. Notez que le fait d'ajouter un composant ne provoque nullement l'affichage de celui-ci à l'écran. Cette méthode add() est surdéfinie de façon à pouvoir spécifier, dans un premier argument, le positionnement du composant spécifié en deuxième. Notez que cela n'a parfois aucun effet avec certains containers.

Si l'on désire déplacer un composant, il suffit d'appliquer la méthode move() à ce composant, en spécifiant respectivement l'abscisse et l'ordonnée voulues. Citons enfin la méthode resize() qui permet de définir les nouvelles largeur et hauteur d'un composant.

Il existe principalement deux types de containers. Ceux de type Panel, permettant de disposer des groupes d'éléments dans une fenêtre, et Window pour définir des fenêtres principales (Frame) ou des fenêtres de dialogue (Dialog).

Etudions maitenant les layouts. Il faut tout d'abord savoir que tout container possède un layout manager ou gestionnaire de positionnement, chargé, comme nous l'avons dit, d'imposer une certaine disposition aux composants qu'il reçoit. Ce layout manager se présente sous la forme d'une interface dont plusieurs implémentations particulières sont proposées en standard. Listons les principales implémentations :

Il est important de noter que, pour une fenêtre, le layout par défaut est le BorderLayout.

Avant de passer à la gestion des événements, prenons un exemple permettant d'illustrer ce que nous avant vu dans ce chapitre.

// Interface.java

//

import java.awt.*;

class Interface {

public static void main (String arg[]) {

// On crée une fenêtre de type Frame

Window win = new Frame("Exemple d'interface AWT");

// On crée un objet Panel

Panel p = new Panel();

// On utilise FlowLayout comme Layout

// Manager

p.setLayout (new FlowLayout ());

// On ajoute un Label et un bouton

p.add (new Label("Cliquer sur le bouton pour continuer "));

p.add (new Button("Bouton"));

// On ajoute le panel à la fenêtre

win.add ("Center", p);

// Affichage

win.show ();

win.pack ();

}

}

Détaillons le contenu de ce fichier source. On commence par créer une fenêtre de type Frame (on aurait pu créer un Dialog), ayant pour titre "Exemple d'interface AWT". Cette fenêtre utilise par défaut le BorderLayout. On crée ensuite un objet Panel, qui nous permettra d'ajouter des éléments dans la fenêtre. On choisit, pour ce Panel, d'utiliser le FlowLayout car il est plus simple à utiliser que le BorderLayout. On met dans ce panel deux composants, grâce à la méthode add(), à savoir un label et un bouton. Ensuite, nous indiquons à quel endroit de la fenêtre on désire mettre le Panel (win.add ("Center", p);), en l'occurrence, au centre. Enfin, nous faisons appel à deux méthodes, show(), permettant d'afficher la fenêtre à l'écran et pack() qui est utilisé pour demander au Layout Manager de disposer les composants le mieux possible.

Lorsqu'on exécute le programme précédent, la fenêtre suivante s'affiche à l'écran :

Si vous tentez de cliquer sur le bouton, il ne se passera rien car nous n'avons installé aucun gestionnaire d'événements. Voyons donc maintenant comment gérer ces événements avec l'AWT.

 

4. Gestion des événements

Un événement est généré, rappelons-le, sur intervention de l'utilisateur. Il peut s'agir d'un clic de souris, de l'appui sur une touche ou encore du rafraîchissement de l'affichage. Lorsqu'un événement se produit, il y a appel à la méthode handleEvent() de la classe Component. Pour l'utiliser, il suffit de créer une classe dérivée d'un composant et de redéfinir la méthode handleEvent(). Il faut noter que cette méthode prend en argument un événement de type Event et qu'elle doit renvoyer un booléen valant true si elle a traité l'événement ou false si cet événement doit remonter au gestionnaire du composant père. Par défaut, la méthode retourne false.

Voici un exemple illustrant la redéfinition de la méthode handleEvent() et la remontée des événements.

// Evenement.java

//

import java.awt.*;

class Evenement {

public static void main (String arg[]) {

// On crée une fenêtre de type Frame

Window win = new Frame2("Exemple d'interface AWT");

// On crée un objet Panel

Panel p = new Panel2();

// On ajoute le panel à la fenêtre

win.add ("Center", p);

// Affichage

win.pack ();

win.show ();

}

}

class Frame2 extends Frame {

Frame2 (String titre) {

super(titre);

}

public boolean handleEvent (Event e) {

System.out.println("Frame");

return false;

}

}

class Panel2 extends Panel {

Panel2 () {

// On utilise FlowLayout comme Layout

// Manager

setLayout (new FlowLayout ());

// On ajoute un Label et un bouton

add (new Label("Cliquer sur le bouton pour continuer "));

add(new Button2("Bouton"));

}

public boolean handleEvent (Event e) {

System.out.println("Panel");

return false;

}

}

class Button2 extends Button {

Button2 (String texte) {

super(texte);

}

public boolean handleEvent (Event e) {

System.out.println("Button");

return false;

}

}

Cet exemple est inspiré du précédent, nous ne détaillerons donc pas son fonctionnement. Notons cependant que les constructeurs créés dans les classes dérivées appellent leur constructeur parent respectif via le mot clé super.

Il faut également savoir que l'AWT propose un certain nombre de méthodes, comme mouseExit(), KeyDown() etc. qui son appelées quand l'événement auquel elles sont associées se produit. Cela permet de ne pas avoir à traiter toutes les événements possibles dans la méthode handleEvent(). Nous n'en dirons pas plus sur l'AWT, sachant que l'AWT 1.1 apporte d'importantes modifications quant à la gestion des événements.