|
|
|
13) Création de fenêtres & d'Applets |
|
|
|
Texte original |
|
Traducteur :
P. Boite |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
To be able to write a single
ActionListener, I’ve used the somewhat risky approach of checking
the String labels on the buttons. The problem with this is that
it’s easy to get the label a little bit wrong, typically in
capitalization, and this bug can be hard to spot.
|
|
Pour pouvoir écrire un seul ActionListener, j'ai utilisé
l'approche un peu risquée de tester les Strings des labels sur les boutons. Le
problème de cette technique est qu'il est facile de se tromper légèrement dans les labels,
classiquement dans les majuscules et minuscules, et ce bug peut être difficile à
détecter.
|
|
|
|
Note that showOptionDialog( )
and showInputDialog( ) provide return objects that contain the value
entered by the user.
|
|
On remarquera que showOptionDialog() et
showInputDialog() retournent des objets contenant la valeur entrée par
l'utilisateur.
|
|
|
|
Menus
|
|
Menus
|
|
|
|
Each component capable of holding a menu,
including JApplet, JFrame, JDialog, and their descendants,
has a setJMenuBar( ) method that accepts a JMenuBar (you can
have only one JMenuBar on a particular component). You add JMenus
to the JMenuBar, and JMenuItems to the JMenus. Each
JMenuItem can have an ActionListener attached to it, to be fired
when that menu item is selected.
|
|
Chaque composant capable de contenir un menu, y compris
JApplet, JFrame, JDialog et leurs descendants,
possède une méthode setJMenuBar() qui prend comme paramètre un
JMenuBar (il ne peut y avoir qu'un seul JMenuBar sur un composant
donné). On ajoute les JMenus au JMenuBar, et les
JMenuItems aux JMenus. On peut attacher un
ActionListener à chaque JMenuItem, qui sera lancé quand l'élément
de menu est sélectionné.
|
|
|
|
Unlike a system that uses resources, with Java and Swing you must hand assemble all the menus in source code. Here is a very simple menu example:
|
|
Contrairement à un système qui utilise des ressources, en Java et Swing il
faut assembler à la main tous les menus dans le code source. Voici un exemple très simple de menu
:
|
|
|
|
//: c13:SimpleMenus.java
// <applet code=SimpleMenus
// width=200 height=75> </applet>
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import com.bruceeckel.swing.*;
public class SimpleMenus extends JApplet {
JTextField t = new JTextField(15);
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent e){
t.setText(
((JMenuItem)e.getSource()).getText());
}
};
JMenu[] menus = { new JMenu("Winken"),
new JMenu("Blinken"), new JMenu("Nod") };
JMenuItem[] items = {
new JMenuItem("Fee"), new JMenuItem("Fi"),
new JMenuItem("Fo"), new JMenuItem("Zip"),
new JMenuItem("Zap"), new JMenuItem("Zot"),
new JMenuItem("Olly"), new JMenuItem("Oxen"),
new JMenuItem("Free") };
public void init() {
for(int i = 0; i < items.length; i++) {
items[i].addActionListener(al);
menus[i%3].add(items[i]);
}
JMenuBar mb = new JMenuBar();
for(int i = 0; i < menus.length; i++)
mb.add(menus[i]);
setJMenuBar(mb);
Container cp = getContentPane();
cp.setLayout(new FlowLayout());
cp.add(t);
}
public static void main(String[] args) {
Console.run(new SimpleMenus(), 200, 75);
}
} ///:~
|
|
//: c13:SimpleMenus.java // <applet code=SimpleMenus // width=200 height=75> </applet> import javax.swing.*; import java.awt.event.*; import java.awt.*; import com.bruceeckel.swing.*;
public class SimpleMenus extends JApplet { JTextField t = new JTextField(15); ActionListener al = new ActionListener() { public void actionPerformed(ActionEvent e){ t.setText( ((JMenuItem)e.getSource()).getText()); } }; JMenu[] menus = { new JMenu("Winken"), new JMenu("Blinken"), new JMenu("Nod") }; JMenuItem[] items = { new JMenuItem("Fee"), new JMenuItem("Fi"), new JMenuItem("Fo"), new JMenuItem("Zip"), new JMenuItem("Zap"), new JMenuItem("Zot"), new JMenuItem("Olly"), new JMenuItem("Oxen"), new JMenuItem("Free") }; public void init() { for(int i = 0; i items[i].addActionListener(al); menus[i%3].add(items[i]); } JMenuBar mb = new JMenuBar(); for(int i = 0; i mb.add(menus[i]); setJMenuBar(mb); Container cp = getContentPane(); cp.setLayout(new FlowLayout()); cp.add(t); } public static void main(String[] args) { Console.run(new SimpleMenus(), 200, 75); } } ///:~
|
|
|
|
The use of the modulus operator in
“i%3” distributes the menu items among the three
JMenus. Each JMenuItem must have an ActionListener attached
to it; here, the same ActionListener is used everywhere but you’ll
usually need an individual one for each JMenuItem.
|
|
L'utilisation de l'opérateur modulo [modulus] dans
i%3 distribue les éléments de menus parmi les trois JMenus.
Chaque JMenuItem doit avoir un ActionListener attaché ; ici le même
ActionListener est utilisé partout mais on en aura besoin normalement d'un pour
chaque JMenuItem.
|
|
|
|
JMenuItem
inherits AbstractButton, so it has some buttonlike behaviors. By
itself, it provides an item that can be placed on a drop-down menu. There are
also three types inherited from JMenuItem: JMenu to hold other
JMenuItems (so you can have cascading menus), JCheckBoxMenuItem,
which produces a checkmark to indicate whether that menu item is selected, and
JRadioButtonMenuItem, which contains a radio button.
|
|
JMenuItem hérite d'AbstractButton,
et il a donc certains comportements des boutons. En lui-même, il fournit un élément qui peut être
placé dans un menu déroulant. Il y a aussi trois types qui héritent de JMenuItem :
JMenu pour contenir d'autres JMenuItems (pour réaliser des menus
en cascade), JCheckBoxMenuItem, qui fournit un marquage pour indiquer si l'élément
de menu est sélectionné ou pas, et JRadioButtonMenuItem, qui contient un bouton
radio.
|
|
|
|
As a more sophisticated example, here are
the ice cream flavors again, used to create menus. This example also shows
cascading menus, keyboard mnemonics, JCheckBoxMenuItems, and the
way you can dynamically change menus:
|
|
En tant qu'exemple plus sophistiqué, voici à nouveau les parfums de crèmes
glacées, utilisés pour créer des menus. Cet exemple montre également des menus en cascade, des
mnémoniques clavier, des JCheckBoxMenuItems, et la façon de changer ces menus
dynamiquement :
|
|
|
|
//: c13:Menus.java
// Submenus, checkbox menu items, swapping menus,
// mnemonics (shortcuts) and action commands.
// <applet code=Menus width=300
// height=100> </applet>
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import com.bruceeckel.swing.*;
public class Menus extends JApplet {
String[] flavors = { "Chocolate", "Strawberry",
"Vanilla Fudge Swirl", "Mint Chip",
"Mocha Almond Fudge", "Rum Raisin",
"Praline Cream", "Mud Pie" };
JTextField t = new JTextField("No flavor", 30);
JMenuBar mb1 = new JMenuBar();
JMenu
f = new JMenu("File"),
m = new JMenu("Flavors"),
s = new JMenu("Safety");
// Alternative approach:
JCheckBoxMenuItem[] safety = {
new JCheckBoxMenuItem("Guard"),
new JCheckBoxMenuItem("Hide")
};
JMenuItem[] file = {
new JMenuItem("Open"),
};
// A second menu bar to swap to:
JMenuBar mb2 = new JMenuBar();
JMenu fooBar = new JMenu("fooBar");
JMenuItem[] other = {
// Adding a menu shortcut (mnemonic) is very
// simple, but only JMenuItems can have them
// in their constructors:
new JMenuItem("Foo", KeyEvent.VK_F),
new JMenuItem("Bar", KeyEvent.VK_A),
// No shortcut:
new JMenuItem("Baz"),
};
JButton b = new JButton("Swap Menus");
class BL implements ActionListener {
public void actionPerformed(ActionEvent e) {
JMenuBar m = getJMenuBar();
setJMenuBar(m == mb1 ? mb2 : mb1);
validate(); // Refresh the frame
}
}
class ML implements ActionListener {
public void actionPerformed(ActionEvent e) {
JMenuItem target = (JMenuItem)e.getSource();
String actionCommand =
target.getActionCommand();
if(actionCommand.equals("Open")) {
String s = t.getText();
boolean chosen = false;
for(int i = 0; i < flavors.length; i++)
if(s.equals(flavors[i])) chosen = true;
if(!chosen)
t.setText("Choose a flavor first!");
else
t.setText("Opening "+ s +". Mmm, mm!");
}
}
}
class FL implements ActionListener {
public void actionPerformed(ActionEvent e) {
JMenuItem target = (JMenuItem)e.getSource();
t.setText(target.getText());
}
}
// Alternatively, you can create a different
// class for each different MenuItem. Then you
// Don't have to figure out which one it is:
class FooL implements ActionListener {
public void actionPerformed(ActionEvent e) {
t.setText("Foo selected");
}
}
class BarL implements ActionListener {
public void actionPerformed(ActionEvent e) {
t.setText("Bar selected");
}
}
class BazL implements ActionListener {
public void actionPerformed(ActionEvent e) {
t.setText("Baz selected");
}
}
class CMIL implements ItemListener {
public void itemStateChanged(ItemEvent e) {
JCheckBoxMenuItem target =
(JCheckBoxMenuItem)e.getSource();
String actionCommand =
target.getActionCommand();
if(actionCommand.equals("Guard"))
t.setText("Guard the Ice Cream! " +
"Guarding is " + target.getState());
else if(actionCommand.equals("Hide"))
t.setText("Hide the Ice Cream! " +
"Is it cold? " + target.getState());
}
}
public void init() {
ML ml = new ML();
CMIL cmil = new CMIL();
safety[0].setActionCommand("Guard");
safety[0].setMnemonic(KeyEvent.VK_G);
safety[0].addItemListener(cmil);
safety[1].setActionCommand("Hide");
safety[0].setMnemonic(KeyEvent.VK_H);
safety[1].addItemListener(cmil);
other[0].addActionListener(new FooL());
other[1].addActionListener(new BarL());
other[2].addActionListener(new BazL());
FL fl = new FL();
for(int i = 0; i < flavors.length; i++) {
JMenuItem mi = new JMenuItem(flavors[i]);
mi.addActionListener(fl);
m.add(mi);
// Add separators at intervals:
if((i+1) % 3 == 0)
m.addSeparator();
}
for(int i = 0; i < safety.length; i++)
s.add(safety[i]);
s.setMnemonic(KeyEvent.VK_A);
f.add(s);
f.setMnemonic(KeyEvent.VK_F);
for(int i = 0; i < file.length; i++) {
file[i].addActionListener(fl);
f.add(file[i]);
}
mb1.add(f);
mb1.add(m);
setJMenuBar(mb1);
t.setEditable(false);
Container cp = getContentPane();
cp.add(t, BorderLayout.CENTER);
// Set up the system for swapping menus:
b.addActionListener(new BL());
b.setMnemonic(KeyEvent.VK_S);
cp.add(b, BorderLayout.NORTH);
for(int i = 0; i < other.length; i++)
fooBar.add(other[i]);
fooBar.setMnemonic(KeyEvent.VK_B);
mb2.add(fooBar);
}
public static void main(String[] args) {
Console.run(new Menus(), 300, 100);
}
} ///:~
|
|
//: c13:Menus.java // Sous-menus, éléments de menu avec boîtes à cocher, permutations de menus, // mnémoniques (raccourcis) et commandes d'actions. // <applet code=Menus width=300 // height=100> </applet> import javax.swing.*; import java.awt.*; import java.awt.event.*; import com.bruceeckel.swing.*;
public class Menus extends JApplet { String[] flavors = { "Chocolate", "Strawberry", "Vanilla Fudge Swirl", "Mint Chip", "Mocha Almond Fudge", "Rum Raisin", "Praline Cream", "Mud Pie" }; JTextField t = new JTextField("No flavor", 30); JMenuBar mb1 = new JMenuBar(); JMenu f = new JMenu("File"), m = new JMenu("Flavors"), s = new JMenu("Safety"); // Approche alternative : JCheckBoxMenuItem[] safety = { new JCheckBoxMenuItem("Guard"), new JCheckBoxMenuItem("Hide") }; JMenuItem[] file = { new JMenuItem("Open"), }; // Une seconde barre de menu pour échanger : JMenuBar mb2 = new JMenuBar(); JMenu fooBar = new JMenu("fooBar"); JMenuItem[] other = { // Ajouter un raccourci de menu (mnémonique) est très // simple, mais seuls les JMenuItems peuvent les avoir // dans leurs constructeurs: new JMenuItem("Foo", KeyEvent.VK_F), new JMenuItem("Bar", KeyEvent.VK_A), // Pas de raccourci : new JMenuItem("Baz"), }; JButton b = new JButton("Swap Menus"); class BL implements ActionListener { public void actionPerformed(ActionEvent e) { JMenuBar m = getJMenuBar(); setJMenuBar(m == mb1 ? mb2 : mb1); validate(); // Rafraîchissement de la fenêtre } } class ML implements ActionListener { public void actionPerformed(ActionEvent e) { JMenuItem target = (JMenuItem)e.getSource(); String actionCommand = target.getActionCommand(); if(actionCommand.equals("Open")) { String s = t.getText(); boolean chosen = false; for(int i = 0; i if(s.equals(flavors[i])) chosen = true; if(!chosen) t.setText("Choose a flavor first!"); else t.setText("Opening "+ s +". Mmm, mm!"); } } } class FL implements ActionListener { public void actionPerformed(ActionEvent e) { JMenuItem target = (JMenuItem)e.getSource(); t.setText(target.getText()); } } // Alternativement, on peut créer une classe // différente pour chaque JMenuItem. Ensuite // il n'est plus nécessaire de rechercher de laquelle il s'agit : class FooL implements ActionListener { public void actionPerformed(ActionEvent e) { t.setText("Foo selected"); } } class BarL implements ActionListener { public void actionPerformed(ActionEvent e) { t.setText("Bar selected"); } } class BazL implements ActionListener { public void actionPerformed(ActionEvent e) { t.setText("Baz selected"); } } class CMIL implements ItemListener { public void itemStateChanged(ItemEvent e) { JCheckBoxMenuItem target = (JCheckBoxMenuItem)e.getSource(); String actionCommand = target.getActionCommand(); if(actionCommand.equals("Guard")) t.setText("Guard the Ice Cream! " + "Guarding is " + target.getState()); else if(actionCommand.equals("Hide")) t.setText("Hide the Ice Cream! " + "Is it cold? " + target.getState()); } } public void init() { ML ml = new ML(); CMIL cmil = new CMIL(); safety[0].setActionCommand("Guard"); safety[0].setMnemonic(KeyEvent.VK_G); safety[0].addItemListener(cmil); safety[1].setActionCommand("Hide"); safety[0].setMnemonic(KeyEvent.VK_H); safety[1].addItemListener(cmil); other[0].addActionListener(new FooL()); other[1].addActionListener(new BarL()); other[2].addActionListener(new BazL()); FL fl = new FL(); for(int i = 0; i JMenuItem mi = new JMenuItem(flavors[i]); mi.addActionListener(fl); m.add(mi); // Ajout de séparateurs par intervalles: if((i+1) % 3 == 0) m.addSeparator(); } for(int i = 0; i s.add(safety[i]); s.setMnemonic(KeyEvent.VK_A); f.add(s); f.setMnemonic(KeyEvent.VK_F); for(int i = 0; i file[i].addActionListener(fl); f.add(file[i]); } mb1.add(f); mb1.add(m); setJMenuBar(mb1); t.setEditable(false); Container cp = getContentPane(); cp.add(t, BorderLayout.CENTER); // Installation du système d'échange de menus: b.addActionListener(new BL()); b.setMnemonic(KeyEvent.VK_S); cp.add(b, BorderLayout.NORTH); for(int i = 0; i fooBar.add(other[i]); fooBar.setMnemonic(KeyEvent.VK_B); mb2.add(fooBar); } public static void main(String[] args) { Console.run(new Menus(), 300, 100); } } ///:~
|
|
|
|
In this program I placed the menu items
into arrays and then stepped through each array calling add( ) for
each JMenuItem. This makes adding or subtracting a menu item somewhat
less tedious.
|
|
Dans ce programme j'ai placé les éléments de menus dans des tableaux et
ensuite j'ai parcouru chaque tableau en appelant add() pour chaque
JMenuItem. Ceci rend l'ajout ou la suppression d'un élément de menu un peu moins
fastidieux.
|
|
|
|
This program creates not one but two
JMenuBars to demonstrate that menu bars can be actively swapped while the
program is running. You can see how a JMenuBar is made up of
JMenus, and each JMenu is made up of JMenuItems,
JCheckBoxMenuItems, or even other JMenus (which produce submenus).
When a JMenuBar is assembled it can be installed into the current program
with the setJMenuBar( ) method. Note that when the button is
pressed, it checks to see which menu is currently installed by calling
getJMenuBar( ), then it puts the other menu bar in its
place.
|
|
Ce programme crée deux JMenuBars pour démontrer que les
barres de menu peuvent être échangées dynamiquement à l'exécution du programme. On peut voir qu'un
JMenuBar est composé de JMenus, et que chaque
JMenu est composé de JMenuItems,
JCheckBoxMenuItems, ou même d'autres JMenus (qui produisent des
sous-menus). Une fois construit un JMenuBar, il peut être installé dans le
programme courant avec la méthode setJMenuBar(). Remarquons que lorsque le bouton
est cliqué, il regarde quel menu est installé en appelant getJMenuBar(), et à ce
moment il le remplace par l'autre barre de menu.
|
|
|
|
When testing for “Open,”
notice that spelling and capitalization are critical, but Java signals no error
if there is no match with “Open.” This kind of string comparison is
a source of programming errors.
|
|
Lorsqu'on teste "Open", il faut remarquer que l'orthographe et les
majuscules/minuscules sont cruciaux, et que Java ne signale pas d'erreur s'il n'y a pas
correspondance avec "Open". Ce genre de comparaison de chaînes est une source d'erreurs de
programmation.
|
|
|
|
The checking and unchecking of the menu
items is taken care of automatically. The code handling the
JCheckBoxMenuItems shows two different ways to determine what was
checked: string matching (which, as mentioned above, isn’t a very safe
approach although you’ll see it used) and matching on the event target
object. As shown, the getState( ) method can
be used to reveal the state. You can also change the state of a
JCheckBoxMenuItem with setState( ).
|
|
Le cochage et le décochage des éléments de menus est pris en compte
automatiquement. Le code gérant les JCheckBoxMenuItems montre deux façons
différentes de déterminer ce qui a été coché : la correspondance des chaînes (qui, comme mentionné
ci-dessus, n'est pas une approche très sûre bien qu'on la rencontre) et la correspondance de
l'objet cible de l'événement. Il montre aussi que la méthode getState() peut
être utilisée pour connaître son état. On peut également changer l'état d'un
JCheckBoxMenuItem à l'aide de setState().
|
|
|
|
The events for menus are a bit
inconsistent and can lead to confusion:
JMenuItems use ActionListeners, but
JCheckboxMenuItems use ItemListeners. The
JMenu objects can also support
ActionListeners, but that’s not usually helpful. In general,
you’ll attach listeners to each JMenuItem,
JCheckBoxMenuItem, or JRadioButtonMenuItem, but the example shows
ItemListeners and ActionListeners attached to the various menu
components.
|
|
Les événements des menus sont un peu inconsistants et peuvent prêter à
confusion : les JMenuItems utilisent des ActionListeners, mais
les JCheckboxMenuItems utilisent des ItemListeners. Les objets
JMenu peuvent aussi supporter des ActionListeners, mais ce n'est
généralement pas très utile. En général, on attache des listeners à chaque
JMenuItem, JCheckBoxMenuItem, ou
JRadioButtonMenuItem, mais l'exemple montre des ItemListeners et
des ActionListeners attachés aux divers composants de menus.
|
|
|
|
Swing
supports mnemonics, or “keyboard shortcuts,” so you can select
anything derived from AbstractButton (button, menu item, etc.) using the
keyboard instead of the mouse. These are quite simple: for JMenuItem you
can use the overloaded constructor that takes as a second argument the
identifier for the key. However, most AbstractButtons do not have
constructors like this so the more general way to solve the problem is to use
the setMnemonic( ) method. The example above
adds mnemonics to the button and some of the menu items; shortcut indicators
automatically appear on the components.
|
|
Swing supporte les mnémoniques, ou raccourcis clavier, de sorte qu'on peut
sélectionner tout ce qui est dérivé de AbstractButton (bouton, menu, élément, et
cetera) en utilisant le clavier à la place de la souris. C'est assez simple : pour le
JMenuItem on peut utiliser le constructeur surchargé qui prend en deuxième
argument l'identificateur de la touche. Cependant, la plupart des AbstractButtons
n'ont pas ce constructeur; une manière plus générale de résoudre ce problème est d'utiliser la
méthode setMnemonic(). L'exemple ci-dessus ajoute une mnémonique au bouton et à
certains des éléments de menus : les indicateurs de raccourcis apparaissent automatiquement sur les
composants.
|
|
|
|
You
can also see the use of setActionCommand( ). This seems a bit
strange because in each case the “action command” is exactly the
same as the label on the menu component. Why not just use the label instead of
this alternative string? The problem is internationalization. If you retarget
this program to another language, you want to change only the label in the menu,
and not change the code (which would no doubt introduce new errors). So to make
this easy for code that checks the text string associated with a menu component,
the “action command” can be immutable while the menu label can
change. All the code works with the “action command,” so it’s
unaffected by changes to the menu labels. Note that in this program, not all the
menu components are examined for their action commands, so those that
aren’t don’t have their action command set.
|
|
On peut aussi voir l'utilisation de setActionCommand().
Ceci paraît un peu bizarre car dans chaque cas la commande d'action [action command] est
exactement la même que le label sur le composant du menu. Pourquoi ne pas utiliser simplement le
label plutôt que cette chaîne de remplacement ? Le problème est l'internationalisation. Si on
réoriente ce programme vers une autre langue, on désire changer uniquement le label du menu, et pas
le code (ce qui introduirait à coup sûr d'autres erreurs). Donc pour faciliter ceci pour les codes
qui testent la chaîne associée à un composant de menu, la commande d'action peut être invariante
tandis que le label du menu peut changer. Tout le code fonctionne avec la commande d'action, de
sorte qu'il n'est pas touché par les modifications des labels des menus. Remarquons que dans ce
programme on ne recherche pas des commandes d'actions pour tous les composants de menus, de sorte
que ceux qui ne sont pas examinés n'ont pas de commande d'action positionnée.
|
|
|
|
The bulk of the work happens in the
listeners. BL performs the JMenuBar
swapping. In ML, the “figure out who rang” approach is taken
by getting the source of the ActionEvent and
casting it to a JMenuItem, then getting the
action command string to pass it through a cascaded if
statement.
|
|
La plus grosse partie du travail se trouve dans les listeners.
BL effectue l'échange des JMenuBars. Dans ML,
l'approche du "qui a sonné ?" est utilisée en utilisant la source de l'ActionEvent et en l'émettant vers un JMenuItem,
en faisant passer la chaîne de la commande d'action à travers une instruction if
en cascade.
|
|
|
|
The FL listener is simple even
though it’s handling all the different flavors in the flavor menu. This
approach is useful if you have enough simplicity in your logic, but in general,
you’ll want to take the approach used with FooL, BarL, and
BazL, in which they are each attached to only a single menu component so
no extra detection logic is necessary and you know exactly who called the
listener. Even with the profusion of classes generated this way, the code inside
tends to be smaller and the process is more foolproof.
|
|
Le listener FL est simple, bien qu'il gère les
différents parfums du menu parfums. Cette approche est utile si la logique est simple, mais en
général, on utilisera l'approche de FooL, BarL et
BazL, dans lesquels ils sont chacun attaché à un seul composant de menu de sorte
qu'il n'est pas nécessaire d'avoir une logique de détection supplémentaire, et on sait exactement
qui a appelé le listener. Même avec la profusion de classes générées de cette façon, le
code interne tend à être plus petit et le traitement est plus fiable.
|
|
|
|
You can see that menu code quickly gets
long-winded and messy. This is another case where the use of a GUI builder is
the appropriate solution. A good tool will also handle the maintenance of the
menus.
|
|
On peut voir que le code d'un menu devient rapidement long et désordonné.
C'est un autre cas où l'utilisation d'un GUI builder est la solution appropriée. Un bon
outil gérera également la maintenance des menus.
|
|
|
|
Pop-up menus
|
|
Menus pop-up
|
|
|
|
The most straightforward way to implement
a JPopupMenu is to create an inner class that extends
MouseAdapter, then add an object of that inner class to each component
that you want to produce pop-up behavior:
|
|
La façon la plus directe d'implémenter un JPopupMenu est
de créer une classe interne qui étend MouseAdapter, puis d'ajouter un objet de
cette classe interne à chaque composant pour lequel on veut créer le pop-up :
|
|
|
|
//: c13:Popup.java
// Creating popup menus with Swing.
// <applet code=Popup
// width=300 height=200></applet>
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import com.bruceeckel.swing.*;
public class Popup extends JApplet {
JPopupMenu popup = new JPopupMenu();
JTextField t = new JTextField(10);
public void init() {
Container cp = getContentPane();
cp.setLayout(new FlowLayout());
cp.add(t);
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent e){
t.setText(
((JMenuItem)e.getSource()).getText());
}
};
JMenuItem m = new JMenuItem("Hither");
m.addActionListener(al);
popup.add(m);
m = new JMenuItem("Yon");
m.addActionListener(al);
popup.add(m);
m = new JMenuItem("Afar");
m.addActionListener(al);
popup.add(m);
popup.addSeparator();
m = new JMenuItem("Stay Here");
m.addActionListener(al);
popup.add(m);
PopupListener pl = new PopupListener();
addMouseListener(pl);
t.addMouseListener(pl);
}
class PopupListener extends MouseAdapter {
public void mousePressed(MouseEvent e) {
maybeShowPopup(e);
}
public void mouseReleased(MouseEvent e) {
maybeShowPopup(e);
}
private void maybeShowPopup(MouseEvent e) {
if(e.isPopupTrigger()) {
popup.show(
e.getComponent(), e.getX(), e.getY());
}
}
}
public static void main(String[] args) {
Console.run(new Popup(), 300, 200);
}
} ///:~
|
|
//: c13:Popup.java // Création de menus popup avec Swing. // <applet code=Popup // width=300 height=200></applet> import javax.swing.*; import java.awt.*; import java.awt.event.*; import com.bruceeckel.swing.*;
public class Popup extends JApplet { JPopupMenu popup = new JPopupMenu(); JTextField t = new JTextField(10); public void init() { Container cp = getContentPane(); cp.setLayout(new FlowLayout()); cp.add(t); ActionListener al = new ActionListener() { public void actionPerformed(ActionEvent e){ t.setText( ((JMenuItem)e.getSource()).getText()); } }; JMenuItem m = new JMenuItem("Hither"); m.addActionListener(al); popup.add(m); m = new JMenuItem("Yon"); m.addActionListener(al); popup.add(m); m = new JMenuItem("Afar"); m.addActionListener(al); popup.add(m); popup.addSeparator(); m = new JMenuItem("Stay Here"); m.addActionListener(al); popup.add(m); PopupListener pl = new PopupListener(); addMouseListener(pl); t.addMouseListener(pl); } class PopupListener extends MouseAdapter { public void mousePressed(MouseEvent e) { maybeShowPopup(e); } public void mouseReleased(MouseEvent e) { maybeShowPopup(e); } private void maybeShowPopup(MouseEvent e) { if(e.isPopupTrigger()) { popup.show( e.getComponent(), e.getX(), e.getY()); } } } public static void main(String[] args) { Console.run(new Popup(), 300, 200); } } ///:~
|
|
|
|
The same
ActionListener is added to each JMenuItem, so that it fetches the
text from the menu label and inserts it into the
JTextField.
|
|
Le même ActionListener est ajouté à chaque
JMenuItem de façon à prendre le texte du label du menu et l'insérer dans le
JTextField.
|
|
|
|
Drawing
|
|
Dessiner
|
|
|
|
In a good GUI framework, drawing should
be reasonably easy—and it is, in the Swing library. The problem with any
drawing example is that the calculations that determine where things go are
typically a lot more complicated that the calls to the drawing routines, and
these calculations are often mixed together with the drawing calls so it can
seem that the interface is more complicated than it actually
is.
|
|
Dans un bon outil de GUI, dessiner devrait être assez facile, et ça l'est
dans la bibliothèque Swing. Le problème de tout exemple de dessin est que les calculs qui
déterminent où vont les éléments sont souvent beaucoup plus compliqués que les appels aux
sous-programmes de dessin, et que ces calculs sont souvent mélangés aux appels de dessin, de sorte
que l'interface semble plus compliquée qu'elle ne l'est.
|
|
|
|
For simplicity, consider the problem of
representing data on the screen—here, the data will be provided by the
built-in Math.sin( ) method which is a mathematical sine function.
To make things a little more interesting, and to further demonstrate how easy it
is to use Swing components, a slider will be placed at the bottom of the form to
dynamically control the number of sine wave cycles that are displayed. In
addition, if you resize the window, you’ll see that the sine wave refits
itself to the new window size.
|
|
Pour simplifier, considérons le problème de la représentation de données
sur l'écran. Ici, les données sont fournies par la méthode intrinsèque Math.sin()
qui est la fonction mathématique sinus. Pour rendre les choses un peu plus intéressantes, et pour
mieux montrer combien il est facile d'utiliser les composants Swing, un curseur sera placé en bas
du formulaire pour contrôler dynamiquement le nombre de cycles du sinus affiché. De plus, si on
redimensionne la fenêtre, on verra le sinus s'adapter de lui-même à la nouvelle taille de la
fenêtre.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|