 |
 |
13) Création de fenêtres & d'Applets |
|
 |
|
Texte original |
 |
Traducteur :
P. Boite |
|
 |
|
 |
 |
 |
 |
 |
 |
|
 |
|
 |
 |
 |
Visual programming and
Beans
|
 |
Programmation visuelle et Beans
|
 |
 |
 |
So far in this book you’ve seen how
valuable Java is for creating reusable pieces of code. The “most
reusable” unit of code has been the class, since it comprises a cohesive
unit of characteristics (fields) and behaviors (methods) that can be reused
either directly via composition or through inheritance.
|
 |
Jusqu'ici, dans ce livre, nous avons vu que Java permet de créer des
morceaux de code réutilisables. L'unité de code la plus réutilisable est la classe, car elle
contient un ensemble cohérent de caractéristiques (champs) et comportements (méthodes) qui peuvent
être réutilisées soit directement par combinaison, soit par héritage.
|
 |
 |
 |
Inheritance and polymorphism are
essential parts of object-oriented programming, but in the majority of cases
when you’re putting together an application, what you really want is
components that do exactly what you need. You’d like to drop these parts
into your design like the electronic engineer puts together chips on a circuit
board. It seems, too, that there should be some way to accelerate this
“modular assembly” style of programming.
|
 |
L'héritage et le polymorphisme sont des éléments essentiels de la
programmation orientée objet, mais dans la majorité des cas, lorsqu'on bâtit une application, en
fait on désire disposer de composants qui font exactement ce qu'on veut. On aimerait placer ces
éléments dans notre conception comme l'ingénieur électronicien qui assemble des puces sur un
circuit. On sent bien qu'il devrait y avoir une façon d'accélérer ce style de programmation
modulaire.
|
 |
 |
 |
“Visual
programming” first became successful—very
successful—with Microsoft’s Visual Basic (VB), followed by a
second-generation design in Borland’s Delphi (the primary inspiration for
the JavaBeans design). With these programming tools the components are
represented visually, which makes sense since they usually display some kind of
visual component such as a button or a text field. The visual representation, in
fact, is often exactly the way the component will look in the running program.
So part of the process of visual programming involves dragging a component from
a palette and dropping it onto your form. The
application builder tool writes
code as you do this, and that code will cause the component to be created in the
running program.
|
 |
La programmation visuelle est devenue très populaire d'abord avec le Visual
Basic (VB) de Microsoft, ensuite avec une seconde génération d'outils, avec Delphi de Borland
(l'inspiration principale de la conception des JavaBeans). Avec ces outils de programmation, les
composants sont représentés visuellement, ce qui est logique car ils affichent d'habitude un
composant visuel tel qu'un bouton ou un champ de texte. La représentation visuelle est en fait
souvent exactement l'aspect du composant lorsque le programme tournera. Une partie du processus de
programmation visuelle consiste à faire glisser un composant d'une palette pour le déposer dans un
formulaire. Pendant qu'on fait cette opération, l'outil de construction d'applications génère du
code, et ce code entraînera la création du composant lors de l'exécution du programme.
|
 |
 |
 |
Simply dropping the component onto a form
is usually not enough to complete the program. Often, you must change the
characteristics of a component, such as what color it is, what text is on it,
what database it’s connected to, etc. Characteristics that can be modified
at design time are referred to as
properties. You can
manipulate the properties of your component inside the application builder tool,
and when you create the program this configuration data is saved so that it can
be rejuvenated when the program is started.
|
 |
Le simple fait de déposer des composants dans un formulaire ne suffit
généralement pas à compléter le programme. Il faut souvent modifier les caractéristiques d'un
composant, telles que sa couleur, son texte, à quelle base de données il est connecté, et cetera.
Des caractéristiques pouvant être modifiées au moment de la conception s'appellent des
propriétés [properties]. On peut manipuler les propriétés du composant dans l'outil de
construction d'applications, et ces données de configuration sont sauvegardées lors de la
construction du programme, de sorte qu'elles puissent être régénérées lors de son
exécution.
|
 |
 |
 |
By now you’re probably used to the
idea that an object is more than characteristics; it’s also a set of
behaviors. At design-time, the behaviors of a visual component are partially
represented by events,
meaning “Here’s something that can happen to the component.”
Ordinarily, you decide what you want to happen when an event occurs by tying
code to that event.
|
 |
Vous êtes probablement maintenant habitués à l'idée qu'un objet est plus
que des caractéristiques ; c'est aussi un ensemble de comportements. A la conception, les
comportements d'un composant visuel sont partiellement représentés par des événements
[events], signifiant : «ceci peut arriver à ce composant». En général on décide de ce qui se
passera lorsqu'un événement apparaît en liant du code à cet événement.
|
 |
 |
 |
Here’s
the critical part: the application builder tool uses reflection to dynamically
interrogate the component and find out which properties and events the component
supports. Once it knows what they are, it can display the properties and allow
you to change those (saving the state when you build the program), and also
display the events. In general, you do something like double-clicking on an
event and the application builder tool creates a code body and ties it to that
particular event. All you have to do at that point is write the code that
executes when the event occurs.
|
 |
C'est ici que se trouve le point critique du sujet : l'outil de
construction d'applications utilise la réflexion pour interroger dynamiquement le composant et
découvrir quelles propriétés et événements le composant accepte. Une fois connues, il peut afficher
ces propriétés et en permettre la modification (tout en sauvegardant l'état lors de la construction
du programme), et afficher également les événements. En général, on double-clique sur un événement
et l'outil crée la structure du code relié à cet événement. Tout ce qu'il reste à faire est
d'écrire le code qui s'exécute lorsque cet événement arrive.
|
 |
 |
 |
All this adds up to a lot of work
that’s done for you by the application builder tool. As a result you can
focus on what the program looks like and what it is supposed to do, and rely on
the application builder tool to manage the connection details for you. The
reason that visual programming tools have been so successful is that they
dramatically speed up the process of building an application—certainly the
user interface, but often other portions of the application as
well.
|
 |
Tout ceci fait qu'une bonne partie du travail est faite par l'outil de
construction d'applications. On peut alors se concentrer sur l'aspect du programme et ce qu'il est
supposé faire, et s'appuyer sur l'outil pour s'occuper du détail des connexions. La raison pour
laquelle les outils de programmation visuels on autant de succès est qu'ils accélèrent fortement le
processus de construction d'une application, l'interface utilisateur à coup sûr, mais également
d'autres parties de l'application.
|
 |
 |
 |
What is a Bean?
|
 |
Qu'est-ce qu'un Bean ?
|
 |
 |
 |
After the dust settles, then, a component
is really just a block of code, typically embodied in a class. The key issue is
the ability for the application builder tool to discover the properties and
events for that component. To create a VB component, the programmer had to write
a fairly complicated piece of code following certain conventions to expose the
properties and events. Delphi was a second-generation visual programming tool
and the language was actively designed around visual programming so it is much
easier to create a visual component. However, Java has brought the creation of
visual components to its most advanced state with JavaBeans, because a Bean is
just a class. You don’t have to write any extra code or use special
language extensions in order to make something a Bean. The only thing you need
to do, in fact, is slightly modify the way that you name your methods. It is the
method name that tells the application builder tool whether this is a property,
an event, or just an ordinary method.
|
 |
Une fois la poussière retombée, un composant est uniquement un bloc de
code, normalement intégré dans une classe. La clé du système est la capacité du constructeur
d'applications de découvrir les propriétés et événements de ce composant. Pour créer un composant
VB, le programmeur devait écrire un bout de code assez compliqué, en suivant certaines conventions
pour exposer les propriétés et événements. Delphi est un outil de programmation visuelle de seconde
génération, pour lequel il est beaucoup plus facile de créer un composant visuel. Java de son côté
a porté la création de composants visuels à son état le plus avancé, avec les JavaBeans, car un
Bean est tout simplement une classe. Il n'y a pas besoin d'écrire de code supplémentaire ou
d'utiliser des extensions particulières du langage pour transformer quelque chose en Bean. La seule
chose à faire, en fait, est de modifier légèrement la façon de nommer les méthodes. C'est le nom de
la méthode qui dit au constructeur d'applications s'il s'agit d'une propriété, d'un événement, ou
simplement une méthode ordinaire.
|
 |
 |
 |
In the Java
documentation, this naming convention is mistakenly termed a “design
pattern.” This is unfortunate, since design patterns (see Thinking in
Patterns with Java, downloadable at www.BruceEckel.com) are
challenging enough without this sort of confusion. It’s not a design
pattern, it’s just a naming convention and it’s fairly
simple:
|
 |
Dans la documentation Java, cette convention de nommage est par erreur
désignée comme un modèle de conception [design pattern]. Ceci est maladroit, car les
modèles de conception (voir Thinking in Patterns with Java, téléchargeable à
www.BruceEckel.com) sont suffisamment difficiles à comprendre sans ajouter ce genre de
confusions. Ce n'est pas un modèle de conception, c'est uniquement une convention de nommage assez
simple :
|
 |
 |
 |
- For a property named
xxx, you typically create two methods: getXxx( ) and
setXxx( ). Note that the first letter after “get” or
“set” is automatically lowercased to produce the property name. The
type produced by the “get” method is the same as the type of the
argument to the “set” method. The name of the property and the type
for the “get” and “set” are not
related.
- For a
boolean property, you can use the “get” and “set”
approach above, but you can also use “is” instead of
“get.”
- Ordinary
methods of the Bean don’t conform to the above naming convention, but
they’re
public.
- For
events, you use the Swing “listener” approach. It’s exactly
the same as you’ve been seeing: addFooBarListener(FooBarListener)
and removeFooBarListener(FooBarListener) to handle a FooBarEvent.
Most of the time the built-in events and listeners will satisfy your needs, but
you can also create your own events and listener
interfaces.
|
 |
- Pour une propriété nommée xxx, on crée deux méthodes :
getXxx() et setXxx(). Remarquons que la première
lettre après get ou set est transformée automatiquement en minuscule pour obtenir le nom de la
propriété. Le type fourni par la méthode get est le même que le type de l'argument de la méthode
set. Le nom de la propriété et le type pour les méthodes get et set ne sont pas liés.
- Pour une propriété de type boolean, on peut utiliser les méthodes get et
set comme ci-dessus, ou utiliser is au lieu de get.
- Les méthodes ordinaires du Bean ne suivent pas la convention de nommage
ci-dessus, mais elles sont public.
- Pour les événements, on utilise la technique Swing du listener.
C'est exactement la même chose que ce qu'on a déjà vu :
addFooBarListener(FooBarListener) et
removeFooBarListener(FooBarListener) pour gérer un FooBarEvent.
La plupart du temps, les événements intégrés satisfont les besoins, mais on peut créer ses propres
événements et interfaces listeners.
|
 |
 |
 |
Point 1 above
answers a question about something you might have noticed when looking at older
code vs. newer code: a number of method names have had small, apparently
meaningless name changes. Now you can see that most of those changes had to do
with adapting to the “get” and “set” naming conventions
in order to make that particular component into a Bean.
|
 |
Le point 1 ci-dessus répond à la question que vous vous êtes peut-être
posée en comparant un ancien et un nouveau code : un certain nombre de méthodes ont subi de petits
changements de noms, apparemment sans raison. On voit maintenant que la plupart de ces changements
avaient pour but de s'adapter aux conventions de nommage get et set de manière à transformer les
composants en Beans.
|
 |
 |
 |
We can use these guidelines to create a simple Bean:
|
 |
On peut utiliser ces règles pour créer un Bean simple :
|
 |
 |
 |
//: frogbean:Frog.java
// A trivial JavaBean.
package frogbean;
import java.awt.*;
import java.awt.event.*;
class Spots {}
public class Frog {
private int jumps;
private Color color;
private Spots spots;
private boolean jmpr;
public int getJumps() { return jumps; }
public void setJumps(int newJumps) {
jumps = newJumps;
}
public Color getColor() { return color; }
public void setColor(Color newColor) {
color = newColor;
}
public Spots getSpots() { return spots; }
public void setSpots(Spots newSpots) {
spots = newSpots;
}
public boolean isJumper() { return jmpr; }
public void setJumper(boolean j) { jmpr = j; }
public void addActionListener(
ActionListener l) {
//...
}
public void removeActionListener(
ActionListener l) {
// ...
}
public void addKeyListener(KeyListener l) {
// ...
}
public void removeKeyListener(KeyListener l) {
// ...
}
// An "ordinary" public method:
public void croak() {
System.out.println("Ribbet!");
}
} ///:~
|
 |
//: frogbean:Frog.java // Un JavaBean trivial. package frogbean; import java.awt.*; import java.awt.event.*;
class Spots {}
public class Frog { private int jumps; private Color color; private Spots spots; private boolean jmpr; public int getJumps() { return jumps; } public void setJumps(int newJumps) { jumps = newJumps; } public Color getColor() { return color; } public void setColor(Color newColor) { color = newColor; } public Spots getSpots() { return spots; } public void setSpots(Spots newSpots) { spots = newSpots; } public boolean isJumper() { return jmpr; } public void setJumper(boolean j) { jmpr = j; } public void addActionListener( ActionListener l) { //... } public void removeActionListener( ActionListener l) { // ... } public void addKeyListener(KeyListener l) { // ... } public void removeKeyListener(KeyListener l) { // ... } // Une méthode public "ordinaire" : public void croak() { System.out.println("Ribbet!"); } } ///:~
|
 |
 |
 |
First, you can see that it’s just a
class. Usually, all your fields will be private, and accessible only
through methods. Following the naming convention, the properties are
jumps, color, spots, and jumper (notice the case
change of the first letter in the property name). Although the name of the
internal identifier is the same as the name of the property in the first three
cases, in jumper you can see that the property name does not force you to
use any particular identifier for internal variables (or, indeed, to even
have any internal variables for that property).
|
 |
Tout d'abord, on voit qu'il s'agit d'une simple classe. En général, tous
les champs seront private, et accessibles uniquement à l'aide des méthodes. En
suivant la convention de nommage, les propriétés sont jumps,
color, spots et jumper (remarquons le passage à
la minuscule pour la première lettre du nom de la propriété). Bien que le nom de l'identificateur
interne soit le même que le nom de la propriété dans les trois premiers cas, dans
jumper on peut voir que le nom de la propriété n'oblige pas à utiliser un
identificateur particulier pour les variables internes (ou même, en fait, d'avoir des
variable internes pour cette propriété).
|
 |
 |
 |
The events this Bean handles are
ActionEvent and KeyEvent, based on the naming of the
“add” and “remove” methods for the associated listener.
Finally, you can see that the ordinary method croak( ) is still part
of the Bean simply because it’s a public method, not because it
conforms to any naming scheme.
|
 |
Les événements gérés par ce Bean sont ActionEvent et
KeyEvent, basés sur le nom des méthodes add et remove pour le listener
associé. Enfin on remarquera que la méthode ordinaire croak() fait toujours partie
du Bean simplement parce qu'il s'agit d'une méthode public, et non parce qu'elle
se conforme à une quelconque convention de nommage.
|
 |
 |
 |
Extracting BeanInfo with the Introspector
|
 |
Extraction des informations sur les Beans [BeanInfo] à l'aide de
l'introspecteur [Introspector]
|
 |
 |
 |
One of the most critical parts of the
Bean scheme occurs when you drag a Bean off a palette and plop it onto a form.
The application builder tool must be able to create the Bean (which it can do if
there’s a default constructor) and then, without access to the
Bean’s source code, extract all the necessary information to create the
property sheet and event handlers.
|
 |
L'un des points critiques du système des Beans est le moment où on fait
glisser un bean d'une palette pour le déposer dans un formulaire. L'outil de construction
d'applications doit être capable de créer le Bean (il y arrive s'il existe un constructeur par
défaut) et, sans accéder au code source du Bean, extraire toutes les informations nécessaires à la
création de la feuille de propriétés et de traitement d'événements.
|
 |
 |
 |
Part of the solution is already evident
from the end of Chapter 12: Java
reflection allows all the
methods of an anonymous class to be discovered. This is perfect for solving the
Bean problem without requiring you to use any extra language keywords like those
required in other visual programming languages. In fact, one of the prime
reasons that reflection was added to Java was to support Beans (although
reflection also supports object serialization and remote method invocation). So
you might expect that the creator of the application builder tool would have to
reflect each Bean and hunt through its methods to find the properties and events
for that Bean.
|
 |
Une partie de la solution est déjà évidente depuis la fin du Chapitre 12 :
la réflexion Java permet de découvrir toutes les méthodes d'une classe anonyme. Ceci est
parfait pour résoudre le problème des Beans, sans avoir accès à des mots clés du langage spéciaux,
comme ceux utilisés dans d'autres langages de programmation visuelle. En fait, une des raisons
principales d'inclure la réflexion dans Java était de permettre les Beans (bien que la réflexion
serve aussi à la sérialisation des objets et à l'invocation de méthodes à distance [RMI :
remote method invocation]). On pourrait donc s'attendre à ce qu'un outil de construction
d'applications doive appliquer la réflexion à chaque Bean et à fureter dans ses méthodes pour
trouver les propriétés et événements de ce Bean.
|
 |
 |
 |
This is certainly possible, but the Java
designers wanted to provide a standard tool, not only to make Beans simpler to
use but also to provide a standard gateway to the creation of more complex
Beans. This tool is the
Introspector class, and
the most important method in this class is the static
getBeanInfo( ). You
pass a Class reference to this method and it fully interrogates that
class and returns a BeanInfo object that you can then dissect to find
properties, methods, and events.
|
 |
Ceci serait certainement possible, mais les concepteurs du langage Java
voulaient fournir un outil standard, non seulement pour rendre les Beans plus faciles à utiliser,
mais aussi pour fournir une plate-forme standard pour la création de Beans plus complexes. Cet
outil est la classe Introspector, la méthode la plus importante de cette classe
est le static getBeanInfo(). On passe la référence d'une
Class à cette méthode , elle l'interroge complètement et retourne un objet
BeanInfo qu'on peut disséquer pour trouver les propriétés, méthodes et
événements.
|
 |
 |
 |
Usually you won’t care about any of
this—you’ll probably get most of your Beans off the shelf from
vendors, and you don’t need to know all the magic that’s going on
underneath. You’ll simply drag your Beans onto your form, then configure
their properties and write handlers for the events you’re interested in.
However, it’s an interesting and educational exercise to use the
Introspector to display information about a Bean, so here’s a tool
that does it:
|
 |
Vous n'aurez probablement pas à vous préoccuper de tout ceci, vous
utiliserez probablement la plupart du temps des beans prêts à l'emploi, et vous n'aurez pas besoin
de connaître toute la magie qui se cache là-dessous. Vous ferez simplement glisser vos Beans dans
des formulaires, vous en configurerez les propriétés et vous écrirez des traitements pour les
événements qui vous intéressent. Toutefois, c'est un exercice intéressant et pédagogique d'utiliser
l'Introspector pour afficher les informations sur un Bean, et voici donc un outil
qui le fait :
|
 |
 |
 |
//: c13:BeanDumper.java
// Introspecting a Bean.
// <applet code=BeanDumper width=600 height=500>
// </applet>
import java.beans.*;
import java.lang.reflect.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import com.bruceeckel.swing.*;
public class BeanDumper extends JApplet {
JTextField query =
new JTextField(20);
JTextArea results = new JTextArea();
public void prt(String s) {
results.append(s + "\n");
}
public void dump(Class bean){
results.setText("");
BeanInfo bi = null;
try {
bi = Introspector.getBeanInfo(
bean, java.lang.Object.class);
} catch(IntrospectionException e) {
prt("Couldn't introspect " +
bean.getName());
return;
}
PropertyDescriptor[] properties =
bi.getPropertyDescriptors();
for(int i = 0; i < properties.length; i++) {
Class p = properties[i].getPropertyType();
prt("Property type:\n " + p.getName() +
"Property name:\n " +
properties[i].getName());
Method readMethod =
properties[i].getReadMethod();
if(readMethod != null)
prt("Read method:\n " + readMethod);
Method writeMethod =
properties[i].getWriteMethod();
if(writeMethod != null)
prt("Write method:\n " + writeMethod);
prt("====================");
}
prt("Public methods:");
MethodDescriptor[] methods =
bi.getMethodDescriptors();
for(int i = 0; i < methods.length; i++)
prt(methods[i].getMethod().toString());
prt("======================");
prt("Event support:");
EventSetDescriptor[] events =
bi.getEventSetDescriptors();
for(int i = 0; i < events.length; i++) {
prt("Listener type:\n " +
events[i].getListenerType().getName());
Method[] lm =
events[i].getListenerMethods();
for(int j = 0; j < lm.length; j++)
prt("Listener method:\n " +
lm[j].getName());
MethodDescriptor[] lmd =
events[i].getListenerMethodDescriptors();
for(int j = 0; j < lmd.length; j++)
prt("Method descriptor:\n " +
lmd[j].getMethod());
Method addListener =
events[i].getAddListenerMethod();
prt("Add Listener Method:\n " +
addListener);
Method removeListener =
events[i].getRemoveListenerMethod();
prt("Remove Listener Method:\n " +
removeListener);
prt("====================");
}
}
class Dumper implements ActionListener {
public void actionPerformed(ActionEvent e) {
String name = query.getText();
Class c = null;
try {
c = Class.forName(name);
} catch(ClassNotFoundException ex) {
results.setText("Couldn't find " + name);
return;
}
dump(c);
}
}
public void init() {
Container cp = getContentPane();
JPanel p = new JPanel();
p.setLayout(new FlowLayout());
p.add(new JLabel("Qualified bean name:"));
p.add(query);
cp.add(BorderLayout.NORTH, p);
cp.add(new JScrollPane(results));
Dumper dmpr = new Dumper();
query.addActionListener(dmpr);
query.setText("frogbean.Frog");
// Force evaluation
dmpr.actionPerformed(
new ActionEvent(dmpr, 0, ""));
}
public static void main(String[] args) {
Console.run(new BeanDumper(), 600, 500);
}
} ///:~
|
 |
//: c13:BeanDumper.java // Introspection d'un Bean. // <applet code=BeanDumper width=600 height=500> // </applet> import java.beans.*; import java.lang.reflect.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; import com.bruceeckel.swing.*;
public class BeanDumper extends JApplet { JTextField query = new JTextField(20); JTextArea results = new JTextArea(); public void prt(String s) { results.append(s + "\n"); } public void dump(Class bean){ results.setText(""); BeanInfo bi = null; try { bi = Introspector.getBeanInfo( bean, java.lang.Object.class); } catch(IntrospectionException e) { prt("Couldn't introspect " + bean.getName()); return; } PropertyDescriptor[] properties = bi.getPropertyDescriptors(); for(int i = 0; i Class p = properties[i].getPropertyType(); prt("Property type:\n " + p.getName() + "Property name:\n " + properties[i].getName()); Method readMethod = properties[i].getReadMethod(); if(readMethod != null) prt("Read method:\n " + readMethod); Method writeMethod = properties[i].getWriteMethod(); if(writeMethod != null) prt("Write method:\n " + writeMethod); prt("===================="); } prt("Public methods:"); MethodDescriptor[] methods = bi.getMethodDescriptors(); for(int i = 0; i prt(methods[i].getMethod().toString()); prt("======================"); prt("Event support:"); EventSetDescriptor[] events = bi.getEventSetDescriptors(); for(int i = 0; i prt("Listener type:\n " + events[i].getListenerType().getName()); Method[] lm = events[i].getListenerMethods(); for(int j = 0; j prt("Listener method:\n " + lm[j].getName()); MethodDescriptor[] lmd = events[i].getListenerMethodDescriptors(); for(int j = 0; j prt("Method descriptor:\n " + lmd[j].getMethod()); Method addListener = events[i].getAddListenerMethod(); prt("Add Listener Method:\n " + addListener); Method removeListener = events[i].getRemoveListenerMethod(); prt("Remove Listener Method:\n " + removeListener); prt("===================="); } } class Dumper implements ActionListener { public void actionPerformed(ActionEvent e) { String name = query.getText(); Class c = null; try { c = Class.forName(name); } catch(ClassNotFoundException ex) { results.setText("Couldn't find " + name); return; } dump(c); } } public void init() { Container cp = getContentPane(); JPanel p = new JPanel(); p.setLayout(new FlowLayout()); p.add(new JLabel("Qualified bean name:")); p.add(query); cp.add(BorderLayout.NORTH, p); cp.add(new JScrollPane(results)); Dumper dmpr = new Dumper(); query.addActionListener(dmpr); query.setText("frogbean.Frog"); // Force evaluation dmpr.actionPerformed( new ActionEvent(dmpr, 0, "")); } public static void main(String[] args) { Console.run(new BeanDumper(), 600, 500); } } ///:~
|
 |
 |
 |
BeanDumper.dump( ) is the
method that does all the work. First it tries to create a BeanInfo
object, and if successful calls the methods of BeanInfo that produce
information about properties, methods, and events. In
Introspector.getBeanInfo( ), you’ll see there is a second
argument. This tells the Introspector where to stop in the inheritance
hierarchy. Here, it stops before it parses all the methods from Object,
since we’re not interested in seeing those.
|
 |
BeanDumper.dump() est la méthode qui fait tout le
travail. Il essaie d'abord de créer un objet BeanInfo, et en cas de succès il
appelle les méthodes de BeanInfo qui fournissent les informations sur les propriétés, méthodes et
événements. Dans Introspector.getBeanInfo(), on voit qu'il y a un second
argument. Celui-ci dit à l'Introspector où s'arrêter dans la hiérarchie
d'héritage. Ici, il s'arrête avant d'analyser toutes les méthodes d'Object, parce
qu'elles ne nous intéressent pas.
|
 |
 |
 |
For properties,
getPropertyDescriptors( )
returns an array of
PropertyDescriptors. For
each PropertyDescriptor you can call
getPropertyType( )
to find the class of object that is passed in and out via the property methods.
Then, for each property you can get its pseudonym (extracted from the method
names) with
getName( ), the
method for reading with
getReadMethod( ),
and the method for writing with
getWriteMethod( ).
These last two methods return a Method object that can actually be used
to invoke the corresponding method on the object (this is part of
reflection).
|
 |
Pour les propriétés, getPropertyDescriptors()
renvoie un tableau de PropertyDescriptors. Pour chaque
PropertyDescriptor, on peut appeler getPropertyType() pour
connaître la classe d'un objet passé par les méthodes de propriétés. Ensuite, on peut obtenir le
nom de chaque propriété (issu du nom des méthodes) à l'aide de getName(), la
méthode pour la lire à l'aide de getReadMethod(), et la méthode pour la
modifier à l'aide de getWriteMethod(). Ces deux dernières méthodes
retournent un objet Method qui peut être utilisé pour appeler la méthode
correspondante de l'objet (ceci fait partie de la réflexion).
|
 |
 |
 |
For the public methods (including
the property methods),
getMethodDescriptors( )
returns an array of
MethodDescriptors. For
each one you can get the associated
Method object and print
its name.
|
 |
Pour les méthodes public (y compris les méthodes des
propriétés), getMethodDescriptors() renvoie un tableau de
MethodDescriptors. Pour chacun de ces descripteurs, on peut obtenir l'objet
Method associé, et imprimer son nom.
|
 |
 |
 |
For the events,
getEventSetDescriptors( )
returns an array of (what else?)
EventSetDescriptors. Each
of these can be queried to find out the class of the listener, the methods of
that listener class, and the add- and remove-listener methods. The BeanDumper
program prints out all of this information.
|
 |
Pour les événements, getEventSetDescriptors()
renvoie un tableau de (que pourrait-il renvoyer d'autre ?) EventSetDescriptors.
Chacun de ces descripteurs peut être utilisé pour obtenir la classe du listener, les
méthodes de cette classe listener, et les méthodes pour ajouter et enlever ce
listener. Le programme BeanDumper imprime toutes ces
informations.
|
 |
 |
 |
Upon startup, the program forces the
evaluation of frogbean.Frog. The output, after removing extra details
that are unnecessary here, is:
|
 |
Au démarrage, le programme force l'évaluation de
frogbean.Frog. La sortie, après suppression de détails inutiles ici, est
:
|
 |
 |
 |
class name: Frog
Property type:
Color
Property name:
color
Read method:
public Color getColor()
Write method:
public void setColor(Color)
====================
Property type:
Spots
Property name:
spots
Read method:
public Spots getSpots()
Write method:
public void setSpots(Spots)
====================
Property type:
boolean
Property name:
jumper
Read method:
public boolean isJumper()
Write method:
public void setJumper(boolean)
====================
Property type:
int
Property name:
jumps
Read method:
public int getJumps()
Write method:
public void setJumps(int)
====================
Public methods:
public void setJumps(int)
public void croak()
public void removeActionListener(ActionListener)
public void addActionListener(ActionListener)
public int getJumps()
public void setColor(Color)
public void setSpots(Spots)
public void setJumper(boolean)
public boolean isJumper()
public void addKeyListener(KeyListener)
public Color getColor()
public void removeKeyListener(KeyListener)
public Spots getSpots()
======================
Event support:
Listener type:
KeyListener
Listener method:
keyTyped
Listener method:
keyPressed
Listener method:
keyReleased
Method descriptor:
public void keyTyped(KeyEvent)
Method descriptor:
public void keyPressed(KeyEvent)
Method descriptor:
public void keyReleased(KeyEvent)
Add Listener Method:
public void addKeyListener(KeyListener)
Remove Listener Method:
public void removeKeyListener(KeyListener)
====================
Listener type:
ActionListener
Listener method:
actionPerformed
Method descriptor:
public void actionPerformed(ActionEvent)
Add Listener Method:
public void addActionListener(ActionListener)
Remove Listener Method:
public void removeActionListener(ActionListener)
====================
|
 |
class name: Frog Property type: Color Property name: color Read method: public Color getColor() Write method: public void setColor(Color) ====================Property type: Spots Property name: spots Read method: public Spots getSpots() Write method: public void setSpots(Spots) ====================Property type: boolean Property name: jumper Read method: public boolean isJumper() Write method: public void setJumper(boolean) ====================Property type: int Property name: jumps Read method: public int getJumps() Write method: public void setJumps(int) ====================Public methods: public void setJumps(int) public void croak() public void removeActionListener(ActionListener) public void addActionListener(ActionListener) public int getJumps() public void setColor(Color) public void setSpots(Spots) public void setJumper(boolean) public boolean isJumper() public void addKeyListener(KeyListener) public Color getColor() public void removeKeyListener(KeyListener) public Spots getSpots() ======================Event support: Listener type: KeyListener Listener method: keyTyped Listener method: keyPressed Listener method: keyReleased Method descriptor: public void keyTyped(KeyEvent) Method descriptor: public void keyPressed(KeyEvent) Method descriptor: public void keyReleased(KeyEvent) Add Listener Method: public void addKeyListener(KeyListener) Remove Listener Method: public void removeKeyListener(KeyListener) ====================Listener type: ActionListener Listener method: actionPerformed Method descriptor: public void actionPerformed(ActionEvent) Add Listener Method: public void addActionListener(ActionListener) Remove Listener Method: public void removeActionListener(ActionListener) ====================
|
 |
 |
 |
 |
 |
 |
 |
 |
|
 |
 |
 |