Types de menu modifier

Swing supporte deux types de menu :

  • les menus de type javax.swing.JMenu attaché à une fenêtre via sa barre de menu javax.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 modifier

Ces 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 classe javax.swing.JMenu dérive de javax.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 modifier

Un 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 modifier

Le 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
				}
			}
		});
	}
}