On voit que chaque type de composant ne supporte que certains

On voit que chaque type de composant ne supporte que certains types d'événements. Il semble assez difficile de
rechercher tous les événements supportés par chaque composant. Une approche plus simple consiste à modifier
le programme ShowMethodsClean.java du chapitre 12 de manière à ce qu'il affiche tous les event listeners
supportés par tout composant Swing entré.
Le chapitre 12 a introduit la réflexion et a utilisé cette fonctionnalité pour rechercher les méthodes d'une classe
donnée, soit une liste complète des méthodes, soit un sous-ensemble des méthodes dont le nom contient un
mot-clé donné. La magie dans ceci est qu'il peut automatiquement nous montrer toutes les méthodes d'une
classe sans qu'on soit obligé de parcourir la hiérarchie des héritages en examinant les classes de base à chaque
niveau. De ce fait, il fournit un outil précieux permettant de gagner du temps pour la programmation : comme
les noms de la plupart des méthodes Java sont parlants et descriptifs, on peut rechercher les noms de méthodes
contenant un mot particulier. Lorsqu'on pense avoir trouvé ce qu'on cherchait, il faut alors vérifier la
documentation en ligne.
Comme dans le chapitre 12 on n'avait pas encore vu Swing, l'outil de ce chapitre était une application de ligne
de commande. En voici une version plus pratique avec interface graphique, spécialisée dans la recherche des
méthodes addListener dans les composants Swing :
//: c13:ShowAddListeners.java
// Affiche les methodes "addXXXListener"
// d'une classe Swing donnee.
// <applet code = ShowAddListeners
// width=500 height=400></applet>
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.reflect.*;
import java.io.*;
import com.bruceeckel.swing.*;
import com.bruceeckel.util.*;
public class ShowAddListeners extends JApplet {
Class cl;
Method[] m;
Constructor[] ctor;
String[] n = new String[0];
JTextField name = new JTextField(25);
JTextArea results = new JTextArea(40, 65);
class NameL implements ActionListener {
1 of 18 7/6/01 9:55 AM
file:///D|/Daniel/TIJ2FR/All/Chapter13c.htm
public void actionPerformed(ActionEvent e) {
String nm = name.getText().trim();
if(nm.length() == 0) {
results.setText("No match");
n=new String[0];
return;
}
try {
cl = Class.forName("javax.swing." + nm);
}catch(ClassNotFoundException ex) {
results.setText("No match");
return;
}
m = cl.getMethods();
// Conversion en un tableau de Strings :
n=new String[m.length];
for(int i = 0; i < m.length; i++)
n[i] = m[i].toString();
reDisplay();
}
}
void reDisplay() {
// Creation de l'ensemble des resultats :
String[] rs = new String[n.length];
int j=0;
for (int i = 0; i < n.length; i++)
if(n[i].indexOf("add")!=-1&&
n[i].indexOf("Listener")!=-1)
rs[j++] =
n[i].substring(n[i].indexOf("add"));
results.setText("");
for (int i=0;i<j;i++)
results.append(
StripQualifiers.strip(rs[i]) + "\n");
2 of 18 7/6/01 9:55 AM
file:///D|/Daniel/TIJ2FR/All/Chapter13c.htm
}
public void init() {
name.addActionListener(new NameL());
JPanel top = new JPanel();
top.add(new JLabel(
"Swing class name (press ENTER):"));
top.add(name);
Container cp = getContentPane();
cp.add(BorderLayout.NORTH, top);
cp.add(new JScrollPane(results));
}
public static void main(String[] args) {
Console.run(new ShowAddListeners(), 500,400);
}
}///:~
La classe StripQualifiers définie au chapitre 12 est réutilisée ici en important la bibliothèque
com.bruceeckel.util.
L'interface utilisateur graphique contient un JTextField name dans lequel on saisit le nom de la classe Swing à
rechercher. Les résultats sont affichés dans une JTextArea.
On remarquera qu'il n'y a pas de boutons ou autres composants pour indiquer qu'on désire lancer la recherche.
C'est parce que le JTextField est surveillé par un ActionListener. Lorsqu'on y fait un changement suivi de
ENTER, la liste est immédiatement mise à jour. Si le texte n'est pas vide, il est utilisé dans Class.forName( )
pour rechercher la classe. Si le nom est incorrect, Class.forName() va échouer, c'est à dire qu'il va émettre une
exception. Celle-ci est interceptée et le JTextArea est positionné à "No match". Mais si on tape un nom correct
(les majuscules/minuscules comptent), Class.forName() réussit et getMethods() retourne un tableau d'objets
Method. Chacun des objets du tableau est transformé en String à l'aide de toString() (cette méthode fournit la
signature complète de la méthode) et ajoutée à n, un tableau de Strings. Le tableau n est un membre de la classe
ShowAddListeners et est utilisé pour mettre à jour l'affichage chaque fois que reDisplay() est appelé.
reDisplay() crée un tableau de Strings appelé rs (pour "result set" : ensemble de résultats). L'ensemble des
résultats est conditionnellement copié depuis les Strings de n qui contiennent add et Listener. indexOf() et
substring() sont ensuite utilisés pour enlever les qualificatifs tels que public, static, etc. Enfin,
StripQualifiers.strip() enlève les qualificatifs de noms.
Ce programme est une façon pratique de rechercher les capacités d'un composant Swing. Une fois connus les
événements supportés par un composant donné, il n'y a pas besoin de rechercher autre chose pour réagir à cet
événement. Il suffit de :
1. Prendre le nom de la classe événement et retirer le mot Event. Ajouter le mot Listener à ce qui reste.
Ceci donne le nom de l'interface listener qu'on doit implémenter dans une classe interne.
2. Implémenter l'interface ci-dessus et écrire les méthodes pour les événements qu'on veut intercepter. Par
exemple, on peut rechercher les événements de déplacement de la souris, et on écrit donc le code pour la
3 of 18 7/6/01 9:55 AM
file:///D|/Daniel/TIJ2FR/All/Chapter13c.htm
méthode mouseMoved() de l'interface MouseMotionListener (il faut également implémenter les autres
méthodes, bien sûr, mais il y a souvent un raccourci que nous verrons bientôt).
3. Créer un objet de la classe listener de l'étape 2. L'enregistrer avec le composant avec la méthode dont le
nom est fourni en ajoutant add au début du nom du listener. Par exemple, addMouseMotionListener( ).
Voici quelques-unes des interfaces listeners :
Interface listener
et adapter Méthodes de l'interface
ActionListener actionPerformed(ActionEvent)
AdjustmentListener adjustmentValueChanged(
AdjustmentEvent)
ComponentListener
ComponentAdapter componentHidden(ComponentEvent)
componentShown(ComponentEvent)
componentMoved(ComponentEvent)
componentResized(ComponentEvent)
ContainerListener
ContainerAdapter componentAdded(ContainerEvent)
componentRemoved(ContainerEvent)
FocusListener
FocusAdapter focusGained(FocusEvent)
focusLost(FocusEvent)
KeyListener
KeyAdapter keyPressed(KeyEvent)
keyReleased(KeyEvent)
keyTyped(KeyEvent)
MouseListener
MouseAdapter mouseClicked(MouseEvent)
mouseEntered(MouseEvent)
mouseExited(MouseEvent)
mousePressed(MouseEvent)
mouseReleased(MouseEvent)
MouseMotionListener
MouseMotionAdapter mouseDragged(MouseEvent)
mouseMoved(MouseEvent)
WindowListener
WindowAdapter windowOpened(WindowEvent)
windowClosing(WindowEvent)
windowClosed(WindowEvent)
windowActivated(WindowEvent)
windowDeactivated(WindowEvent)
windowIconified(WindowEvent)
windowDeiconified(WindowEvent)
ItemListener itemStateChanged(ItemEvent)
Ce n'est pas une liste exhaustive, en partie du fait que le modèle d'événements nous permet de créer nos propres
types d'événements et listeners associés. De ce fait, on rencontrera souvent des bibliothèques qui ont inventé
leurs propres événements, et la connaissance acquise dans ce chapitre nous permettra de comprendre l'utilisation
de ces événements.
Utilisation de listener adapters pour simplifier
Dans le tableau ci-dessus, on peut voir que certaines interfaces listener ne possèdent qu'une seule méthode.
Celles-ci sont triviales à implémenter puisqu'on ne les implémentera que lorsqu'on désire écrire cette méthode
particulière. Par contre, les interfaces listener qui ont plusieurs méthodes peuvent être moins agréables à utiliser.
4 of 18 7/6/01 9:55 AM
file:///D|/Daniel/TIJ2FR/All/Chapter13c.htm
par exemple, quelque chose qu'il faut toujours faire en créant une application est de fournir un
WindowListener au JFrame de manière à pouvoir appeler System.exit() pour sortir de l'application lorsqu'on
reçoit l'événement windowClosing(). Mais comme WindowListener est une interface, il faut implémenter
chacune de ses méthodes même si elles ne font rien. Cela peut être ennuyeux.
Pour résoudre le problème, certaines (mais pas toutes) des interfaces listener qui ont plus d'une méthode
possèdent des adaptateurs [adapters], dont vous pouvez voir les noms dans le tableau ci-dessus. Chaque
adaptateur fournit des méthodes vides par défaut pour chacune des méthodes de l'interface. Ensuite il suffit
d'hériter de cet adaptateur et de redéfinir uniquement les méthodes qu'on doit modifier. Par exemple, le
WindowListener qu'on utilisera normalement ressemble à ceci (souvenez-vous qu'il a été encapsulé dans la
classe Console de com.bruceeckel.swing) :
class MyWindowListener extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
Le seul but des adaptateurs est de faciliter la création des classes listener.
Il y a cependant un désavantage lié aux adaptateurs, sous la forme d'un piège. Supposons qu'on écrive un
WindowAdapter comme celui ci-dessus :
class MyWindowListener extends WindowAdapter {
public void WindowClosing(WindowEvent e) {
System.exit(0);
}
}
Ceci ne marche pas, mais il nous rendra fous à comprendre pourquoi, car tout va compiler et s'exécuter
correctement, sauf que la fermeture de la fenêtre ne fera pas sortir du programme. Voyez-vous le problème ? Il
est situé dans le nom de la méthode : WindowClosing() au lieu de windowClosing(). Une simple erreur de
majuscule se traduit par l'ajout d'une méthode nouvelle. Ce n'est cependant pas cette méthode qui est appelée
lorsque la fenêtre est fermée, de sorte qu'on n'obtient pas le résultat attendu. En dépit de cet inconvénient, une
interface garantit que les méthodes sont correctement implémentées.
Surveiller plusieurs événements
Pour nous prouver que ces événements sont bien déclenchés, et en tant qu'expérience intéressante, créons une
applet qui surveille les autres comportement d'un JButton, autres que le simple fait qu'il soit appuyé ou pas. Cet
exemple montre également comment hériter de notre propre objet bouton, car c'est ce qui est utilisé comme
cible de tous les événements intéressants. Pour cela, il suffit d'hériter de JButton [69].
La classe MyButton est une classe interne de TrackEvent, de sorte que MyButton peut aller dans la fenêtre
parent et manipuler ses champs textes, ce qu'il faut pour pouvoir écrire une information d'état dans les champs
du parent. Bien sûr ceci est une solution limitée, puisque MyButton peut être utilisée uniquement avec
TrackEvent. Ce genre de code est parfois appelé "fortement couplé" :
5 of 18 7/6/01 9:55 AM
file:///D|/Daniel/TIJ2FR/All/Chapter13c.htm
1 / 18 100%

On voit que chaque type de composant ne supporte que certains

La catégorie de ce document est-elle correcte?
Merci pour votre participation!

Faire une suggestion

Avez-vous trouvé des erreurs dans linterface ou les textes ? Ou savez-vous comment améliorer linterface utilisateur de StudyLib ? Nhésitez pas à envoyer vos suggestions. Cest très important pour nous !