L'utilisateur peut rentrer librement du texte dans les champs A et B. Lorsqu'il appuie sur le bouton "+" l'application concatène le texte contenu dans les champs A et B et affiche le résultat de l'opération dans la zone d'affichage. L'utilisateur peut quitter l'application en cliquant sur le bouton "quitter".
Les sources complets des exemples décrits dans ce document sont accessibles en téléchargeant les fichiers Exemple1.tar.gz et Exemple2.tar.gz
Fichier " Main.java " :
class Main {
private static Application application;
public static void main(String[] args) {
application = new Application();
}
}
Nous rappelons qu'une fois compilé, le programme se lance de
la manière suivante :
java Main
import javax.swing.*;
class Application {
private JFrame fenetre;
private JLabel affichage;
private JTextField champA;
private JTextField champB;
private JButton boutonPlus;
private JButton boutonQuitter;
public Application() {
...
}
}
Les objets graphiques sont créés dans le constructeur de la classe. Cela se fait comme suit :
this.fenetre = new JFrame("Une application graphique");
// Le constructeur de JFrame prend en argument le nom de
// la fenêtre
this.affichage = new JLabel();
this.champA = new JTextField(20);
this.champB = new JTextField(20);
// Le constructeur de JTextField prend en argument la taille
// en caractères du champ de saisie
this.boutonPlus = new JButton("+");
// Le constructeur de JButton prend en argument le nom du bouton
this.boutonQuitter = new JButton("Quitter");
Une fois ces composants créés, il faut indiquer la façon
dont ils sont disposés à l'écran. La seule chose que
nous avons besoin d'indiquer pour l'instant est que l'objet fenetre
contient tous les autres composants graphiques. Pour cela il faut récupérer
le "conteneur" de la fenêtre, c'est-à-dire la zone graphique
associée à la fenêtre dans laquelle on peut disposer
d'autres objets graphiques. La méthode getContentPane
de la classe JFrame renvoie le
"conteneur" associé à la fenêtre. C'est un objet de
la classe Container définie
dans le paquetage java.awt. Ajouter
des objets au "conteneur" de la fenêtre se fait simplement à
l'aide de la méthode add
de la classe Container qui prend
en argument l'objet graphique à insérer dans le "conteneur".
Cela n'est cependant pas suffisant. En effet il ne suffit pas de dire quels sont les objets qui seront affichés dans la fenêtre, encore faut il dire comment ces objets seront disposés dans cette fenêtre (en colonnes, les uns à la suite des autres, en cercle, ...). La disposition de composants graphiques dans un objet de type Container est effectuée par des objets particuliers, qu'on appelle des gestionnaires de disposition ("layout managers"). Il faut associer un gestionnaire de disposition au conteneur de la fenêtre par l'intermédiaire de la méthode setLayout de la classe Container. Nous n'avons heureusement pas à écrire les gestionnaires de disposition (même si cela est possible) car la bibliothèque standard Java fournit déjà un certain nombre de classes de gestionnaires de disposition qui correspondent aux situations les plus courantes. Nous utiliserons essentiellement deux types de gestionnaires de disposition :
Container conteneur = fenetre.getContentPane();
FlowLayout disposition = new FlowLayout();
conteneur.setLayout(disposition);
conteneur.add(this.affichage);
conteneur.add(this.champA);
conteneur.add(this.champB);
conteneur.add(this.boutonPlus);
conteneur.add(this.boutonQuitter);
Cela sous-entend naturellement que nous ayons ajouté la ligne
:
import java.awt.*;
au début du fichier " Application.java " afin de pouvoir utiliser la classe Container sans la préfixer par le nom de son paquetage.
Si nous avions voulu organiser les éléments suivant un quadrillage de trois lignes et deux colonnes, nous aurions écrit :
GridLayout disposition = new GridLayout(3, 2);
les autres commandes restant inchangées.
Une fois les objets graphiques disposés à l'intérieur de la fenêtre, il reste deux dernières choses à faire :
this.fenetre.pack();
this.fenetre.setVisible(true);
Ce qui termine l'écriture du constructeur de la classe Application.
NOTE : dès lors que l'on a un programme Java composé de plusieurs fichiers il vaut mieux utiliser la commande suivante :
javac *.java
pour compiler tous les fichiers constituant le programme.
public void actionPerformed(ActionEvent contexte);
L'environnement d'exécution Java scrute constamment les événements souris et clavier et lorsqu'il détecte un clic sur un bouton il invoque la méthode actionPerformed de tous les gestionnaires d'action qui ont été attachés au bouton. L'argument passé à cette méthode contient des informations sur le contexte dans lequel l'action a eu lieu (si par exemple une touche du clavier était enfoncée au moment du clic) qui peuvent être utilisées par le programme. En pratique nous n'en aurons pas besoin et nous n'utiliserons donc jamais cet argument.
Un gestionnaire d'action est une classe qui implémente l'interface ActionListener et qui gère le comportement d'un bouton. Etant donné que nous avons deux boutons nous devons définir deux classes GestionQuitter et GestionPlus implémentant cette interface dans deux fichiers " GestionQuitter.java " et " GestionPlus.java ".
Le gestionnaire d'action le plus simple à définir est celui qui correspond au bouton "quitter". Terminer l'exécution d'un programme se fait en appelant la fonction statique exit de la classe System du paquetage java.lang (importé par défaut par tout programme Java). Cette fonction est en tout point similaire à la fonction exit de C (un code de retour de 0 signifie une sortie normale du programme).
Le fichier " GestionQuitter.java " contient donc :
import java.awt.event.*;
class GestionQuitter implements ActionListener {
public void actionPerformed(ActionEvent contexte) {
System.exit(0);
}
}
Nous devons également affecter un gestionnaire d'action de cette classe au bouton "quitter" de la classe Application. Nous devons donc rajouter dans le constructeur, juste après la construction des objets graphiques, les lignes suivantes :
GestionQuitter gestionQuitter = new GestionQuitter();
this.boutonQuitter.addActionListener(gestionQuitter);
Après recompilation de tous les fichiers et lancement du programme on s'aperçoit que le bouton "quitter" est bien actif.
Le gestionnaire d'action du bouton "+" pose problème car il doit interagir avec les autres composants graphiques de l'application : il doit récupérer le contenu des champs de saisie et modifier la zone d'affichage. Un moyen de résoudre ce problème est de créer dans la classe GestionPlus un champ application qui contient un pointeur sur l'objet Application qui utilise ce gestionnaire d'action. Ainsi le bouton peut avoir accès aux informations contenues dans les composants graphiques de l'application. Comme ceux-ci sont privés il y a deux solutions possibles :
Les méthodes getText et setText définies dans les classes JLabel et JTextField permettent de lire et modifier le contenu de ces objets textuels. Nous ajoutons donc les méthodes suivantes à la classe Application :
public String contenuChampA() {
return this.champA.getText();
}
public String contenuChampB() {
return this.champB.getText();
}
public void afficher(String texte) {
this.affichage.setText(texte);
}
La classe GestionPlus s'écrit alors :
import java.awt.event.*;
class GestionPlus implements ActionListener {
private Application application;
public GestionPlus(Application appli) {
this.application = appli;
}
public void actionPerformed(ActionEvent e) {
this.application.afficher(
this.application.contenuChampA()
+ this.application.contenuChampB()
);
}
}
Le constructeur permet à l'application d'envoyer un pointeur sur elle-même au gestionnaire d'action du bouton. On ajoute donc au constructeur de la classe Application, juste après la construction des objets graphiques, les lignes suivantes :
GestionPlus gestionPlus = new GestionPlus(this);
this.boutonPlus.addActionListener(gestionPlus);
Nous obtenons ainsi une application entièrement opérationnelle.
Les sources complets de l'application se trouvent dans
l'archive
Exemple1.tar.gz
"Exemple1" au même niveau
que ce document HTML.
Container conteneur = fenetre.getContentPane();
GridLayout disposition = new GridLayout(4, 1);
JPanel boutons = new JPanel();
FlowLayout dispositionBoutons = new FlowLayout();
boutons.setLayout(dispositionBoutons);
boutons.add(this.boutonPlus);
boutons.add(this.boutonQuitter);
conteneur.setLayout(disposition);
conteneur.add(this.affichage);
conteneur.add(this.champA);
conteneur.add(this.champB);
conteneur.add(boutons);
Les sources de l'application ainsi modifiée sont disponible dans l'archive Exemple2.tar.gz