Programmation Java Swing/Menus
Types de menu
modifierSwing supporte deux types de menu :
- les menus de type
javax.swing.JMenu
attaché à une fenêtre via sa barre de menujavax.swing.JMenuBar
généralement située en haut de la fenêtre. - les menus de type
javax.swing.JPopupMenu
attaché à tout composant, dont l'affichage est, par exemple, déclenché par un clic droit de la souris.
Création d'un menu
modifierCes deux types de menu (javax.swing.JMenu
et javax.swing.JPopupMenu
) s'utilisent de la même façon.
Un menu est initialement vide, et l'ajout d'un item se fait en appelant l'une des méthodes suivantes :
add(JMenuItem item)
- Ajouter un item de menu.
add(Action action)
- Ajouter un item de menu créé à partir d'une action.
La seconde méthode est préférable car une même action peut être attachée à différents composants (menu, bouton, ...) ce qui simplifie la gestion de son état (état activé ou désactivé, texte, icône, raccourci clavier, ...) dont la modification de répercute sur tous les composants liés.
Il est possible d'ajouter d'autres éléments à un menu :
- La méthode
addSeparator()
permet d'ajouter un séparateur entre deux items de menu. - La méthode
add(JMenuItem item)
accepte aussi un autre menu afin d'ajouter un sous-menu, car la classejavax.swing.JMenu
dérive dejavax.swing.JMenuItem
.
Exemple :
package org.wikibooks.fr.swing;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
* Créer une fenêtre avec un menu.
* @author fr.wikibooks.org
*/
public class ExempleMenuDeFenetre extends JFrame
{
private void menuOuvrir()
{
// Mettre ici le code pour ouvrir un fichier
}
private void menuEnregistrer()
{
// Mettre ici le code pour sauvegarder un fichier
}
public ExempleMenuDeFenetre()
{
// Création de la fenêtre
setTitle("Démonstration de création de menu pour une fenêtre Swing");
Dimension d = new Dimension(500, 200);
setMinimumSize(d);
setSize(d);
// Création des actions
Action a_ouvrir = new AbstractAction("Ouvrir un fichier...")
{
@Override
public void actionPerformed(ActionEvent e)
{
menuOuvrir();
}
};
a_ouvrir.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_O, InputEvent.CTRL_DOWN_MASK)); // Ctrl-O
Action a_enregistrer = new AbstractAction("Enregistrer le fichier...")
{
@Override
public void actionPerformed(ActionEvent e)
{
menuEnregistrer();
}
};
a_enregistrer.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK)); // Ctrl-S
// Création du menu
JMenuBar mb = new JMenuBar();
JMenu m = new JMenu("Fichier"); // Fichier :
mb.add(m);
m.add(new JMenuItem(a_ouvrir)); // - Ouvrir
m.addSeparator(); // ----------------
m.add(new JMenuItem(a_enregistrer)); // - Enregistrer
setJMenuBar(mb); // Attacher la barre de menu à la fenêtre
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
ExempleMenuDeFenetre frame = new ExempleMenuDeFenetre();
frame.setVisible(true);
}
});
}
}
Gestion d'un menu contextuel
modifierUn menu contextuel (classe javax.swing.JPopupMenu
) a la particularité de s'afficher à l'endroit où l'utilisateur a déclenché son affichage (Par exemple, clic droit avec la souris sous Windows ou Linux, ou la touche Menu).
Le déclenchement
modifierLe déclenchement de l'ouverture du menu dépend de la plateforme : il peut se faire lors de l'appui du bouton de souris, ou lors de son relâchement (comme sous Windows par exemple).
La classe MouseEvent
possède une méthode isPopupTrigger()
permettant de tester si l'évènement est celui qui déclenche l'ouverture du menu pour la plateforme.
L'affichage du menu contextuel doit se faire avec la méthode show(JComponent, int, int)
pour que le comportement du menu soit correct : mise en évidence de l'item survolé, gestion de la disparition du menu en cliquant ailleurs, ...
L'utilisation des méthodes setLocation
et setVisible
n'est pas recommandée car le menu peut ne pas fonctionner correctement.
public class UnComposant extends JComponent
{
// ...
private JPopupMenu menu_contextuel;
private boolean ouvrirMenuContextuel(MouseEvent e)
{
if (e.isPopupTrigger())
{
// L'ajustement du menu contextuel est possible ici si besoin, avant l'affichage.
menu_contextuel.show(this, e.getX(), e.getY());
return true; // menu contextuel ouvert
}
return false; // pas d'ouverture pour cet évènement
}
public UnComposant()
{
// ...
menu_contextuel = new JPopupMenu();
// ... ajouter des items au menu ici ...
addMouseListener(new MouseAdapter()
{
@Override
public void mouseReleased(MouseEvent e)
{
// si l'évènement n'est pas pour ouvrir le menu contextuel...
if (!ouvrirMenuContextuel(e))
{
// ... alors faire une autre action
}
}
@Override
public void mousePressed(MouseEvent e)
{
// si l'évènement n'est pas pour ouvrir le menu contextuel...
if (!ouvrirMenuContextuel(e))
{
// ... alors faire une autre action
}
}
});
}
}