Accès rapide :
La vidéo
Structure d'une barre de menu
Décoration d'un JMenuItem
Utilisation d'un mnémonique
Utilisation d'un accélérateur (KeyStroke)
Association d'une icône
Association d'un gestionnaire d'événements
L'exemple de code complet
Cette vidéo vous apprend à coder une barre de menu avec la librairie Java Swing. Les différentes décorations classiques pour vos éléments de menu vous sont aussi présentées : icônes, accélérateurs, mnémoniques, ...
Plusieurs classes de la librairie Swing sont nécessaire pour mettre en oeuvre une barre de menu. Les principales classes sont les suivantes.
javax.swing.JMenuBar : une instance de cette classe représente la barre de menu à proprement parler. Une barre de menu ne s'injecte pas
dans le « content pane ». Au contraire, elle possède son propre emplacement privilégié au sein de la fenêtre, situé juste au dessus
du « content pane ». Utilisez la méthode setJMenuBar
pour placer la barre de menu dans cet emplacement dédié.
javax.swing.JMenu : représente un menu déroulant (« File » ou « Edit » par exemple).
Un tel menu peut être placé soit la la barre de menu principale, soit à l'intérieur d'un autre JMenu
(pour obtenir des sous-menu
déroulants). On peut associer à un JMenu
un mnémonique permettant l'ouverture du menu déroulant par le clavier en appuyant
simultanément sur ALT
et la touche correspondante à ce mnémonique. Un présence d'un mnémonique se repère grâce à la lettre surlignée
dans le texte du menu (voir la capture d'écran ci-dessus ; Le F
du menu File
est son mnémonique).
javax.swing.JMenuItem : représente un élément de ménu (menu item, en anglais), donc un élément cliquable pouvant exécuter un traitement.
Un JMenuItem
peut se voir associer plusieurs « décorations » comme un mnémonique (une lettre pouvant atteindre l'élément de
menu quand il est affiché), un accélérateur permettant un accès directe à l'élément de menu (via la classe KeyStroke
) et une icône
graphique.
javax.swing.ImageIcon : permet de définir une icône graphique associée à un JMenuItem
.
javax.swing.KeyStroke : permet de définir un accélérateur associée à un JMenuItem
(par exemple CTRL+C
pour lancer
une sauvegarde d'un document en cours d'édition).
Il est donc possible de décorer un élément de menu, comme en atteste la capture d'écran suivante.
Pour ajouter un mnémonique, permettant l'ouverture du menu déroulant par le clavier en appuyant simultanément sur ALT
et la touche
correspondante à ce mnémonique, il vous faut invoquer la méthode setMnemonic
. Elle prend en paramètre le caractère (et non pas une chaîne)
associé au menu : ce caractère doit être présent dans la chaîne.
1 2 |
JMenuItem mnuNewFile = new JMenuItem( "New File" ); mnuNewFile.setMnemonic( 'N' ); |
Pour activer cet élément de menu, vous pourrez taper ALT+F
pour ouvrir le menu File
(qui a son propre mnémonique) puis ensuite directement N
pour activer l'élément de menu New File
.
Un accélérateur est un moyen d'accès encore plus rapide que le mnémonique. En effet, il n'est plus nécessaire d'ouvrir le menu contenant notre élément de menu : la séquence de touche lance directement le traitement associé (le listener).
1 2 |
JMenuItem mnuNewFile = new JMenuItem( "New File" ); mnuNewFile.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_N, KeyEvent.CTRL_DOWN_MASK) ); |
Pour rendre votre application esthétique, je vous conseil vivement d'utiliser un jeu d'icônes élégantes. Il y a deux nombreux jeux d'icônes disponible sur Internet.
1 2 |
JMenuItem mnuNewFile = new JMenuItem( "New File" ); mnuNewFile.setIcon( new ImageIcon( "icons/new.png" ) ); |
Vous pouvez récupérer les icônes de l'exemple proposé dans ce tutoriel en téléchargeant ce fichier ZIP.
Un élément de menu (class javax.swing.JMenuItem
) se comporte comme un bouton et c'est normal : la classe JMenuItem
dévive
de la classe AbstractButton
(la classe mère de JButton
). On utilise donc un ActionListener
pour réagir à un
clic sur un élément de menu.
Pour l'implémentation du listener, c'est comme vous voulez : soit vous utiliser une bonne vieille classe anonyme, soit vous utilisez les nouvelles
syntaxes Java 8.0 permettant de produire automatiquement cette classe anonyme (lambda ou référence sur méthode). Personnellement, je trouve que la
syntaxe des références sur méthodes permet d'obtenir un code concis et clair quand-à la définition d'un ActionListener
.
Dans un permier temps, il faut définir une méthode acceptant un ActionEvent
en paramètre. Voici un exemple.
1 2 3 |
private void mnuNewListener( ActionEvent event ) { JOptionPane.showMessageDialog( this, "New File invoked" ); } |
Il ne reste plus qu'à enregistrer l'écouteur qui va être produit grâce à la référence sur méthode (basée, bien entendu, sur la méthode précédemment définie).
Cet enregistrement est réalisé grâce à l'appel de la méthode addActionListener
sur l'élément de menu considéré.
1 2 3 4 |
JMenuItem mnuNewFile = new JMenuItem( "New File" ); // ... mnuNewFile.addActionListener( this::mnuNewListener ); mnuFile.add(mnuNewFile); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.KeyStroke; import javax.swing.UIManager; import javax.swing.plaf.nimbus.NimbusLookAndFeel; public class MenuBarSample extends JFrame { /* Construction de l'interface graphique */ public MenuBarSample() { super( "JMenuBar sample" ); this.setSize(600,400); this.setLocationRelativeTo( null ); this.setDefaultCloseOperation( DISPOSE_ON_CLOSE ); // Construction et injection de la barre de menu this.setJMenuBar( this.createMenuBar() ); } /* Methode de construction de la barre de menu */ private JMenuBar createMenuBar() { // La barre de menu à proprement parler JMenuBar menuBar = new JMenuBar(); // Définition du menu déroulant "File" et de son contenu JMenu mnuFile = new JMenu( "File" ); mnuFile.setMnemonic( 'F' ); JMenuItem mnuNewFile = new JMenuItem( "New File" ); mnuNewFile.setIcon( new ImageIcon( "icons/new.png" ) ); mnuNewFile.setMnemonic( 'N' ); mnuNewFile.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_N, KeyEvent.CTRL_DOWN_MASK) ); mnuNewFile.addActionListener( this::mnuNewListener ); mnuFile.add(mnuNewFile); mnuFile.addSeparator(); JMenuItem mnuOpenFile = new JMenuItem( "Open File ..." ); mnuOpenFile.setIcon( new ImageIcon( "icons/open.png" ) ); mnuOpenFile.setMnemonic( 'O' ); mnuOpenFile.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_O, KeyEvent.CTRL_DOWN_MASK) ); mnuFile.add(mnuOpenFile); JMenuItem mnuSaveFile = new JMenuItem( "Save File ..." ); mnuSaveFile.setIcon( new ImageIcon( "icons/save.png" ) ); mnuSaveFile.setMnemonic( 'S' ); mnuSaveFile.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_DOWN_MASK) ); mnuFile.add(mnuSaveFile); JMenuItem mnuSaveFileAs = new JMenuItem( "Save File As ..." ); mnuSaveFileAs.setIcon( new ImageIcon( "icons/save_as.png" ) ); mnuSaveFileAs.setMnemonic( 'A' ); mnuFile.add(mnuSaveFileAs); mnuFile.addSeparator(); JMenuItem mnuExit = new JMenuItem( "Exit" ); mnuExit.setIcon( new ImageIcon( "icons/exit.png" ) ); mnuExit.setMnemonic( 'x' ); mnuExit.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_F4, KeyEvent.ALT_DOWN_MASK) ); mnuFile.add(mnuExit); menuBar.add(mnuFile); // Définition du menu déroulant "Edit" et de son contenu JMenu mnuEdit = new JMenu( "Edit" ); mnuEdit.setMnemonic( 'E' ); JMenuItem mnuUndo = new JMenuItem( "Undo" ); mnuUndo.setIcon( new ImageIcon( "icons/undo.png" ) ); mnuUndo.setMnemonic( 'U' ); mnuUndo.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_Z, KeyEvent.CTRL_DOWN_MASK) ); mnuEdit.add(mnuUndo); JMenuItem mnuRedo = new JMenuItem( "Redo" ); mnuRedo.setIcon( new ImageIcon( "icons/redo.png" ) ); mnuRedo.setMnemonic( 'R' ); mnuRedo.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_U, KeyEvent.CTRL_DOWN_MASK) ); mnuEdit.add(mnuRedo); mnuEdit.addSeparator(); JMenuItem mnuCopy = new JMenuItem( "Copy" ); mnuCopy.setIcon( new ImageIcon( "icons/copy.png" ) ); mnuCopy.setMnemonic( 'C' ); mnuCopy.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_DOWN_MASK) ); mnuEdit.add(mnuCopy); JMenuItem mnuCut = new JMenuItem( "Cut" ); mnuCut.setIcon( new ImageIcon( "icons/cut.png" ) ); mnuCut.setMnemonic( 't' ); mnuCut.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_X, KeyEvent.CTRL_DOWN_MASK) ); mnuEdit.add(mnuCut); JMenuItem mnuPaste = new JMenuItem( "Paste" ); mnuPaste.setIcon( new ImageIcon( "icons/paste.png" ) ); mnuPaste.setMnemonic( 'P' ); mnuPaste.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_V, KeyEvent.CTRL_DOWN_MASK) ); mnuEdit.add(mnuPaste); menuBar.add(mnuEdit); // Définition du menu déroulant "Help" et de son contenu JMenu mnuHelp = new JMenu( "Help" ); mnuHelp.setMnemonic( 'H' ); menuBar.add( mnuHelp ); return menuBar; } public void mnuNewListener( ActionEvent event ) { JOptionPane.showMessageDialog( this, "Button clicked !" ); } public static void main(String[] args) throws Exception { UIManager.setLookAndFeel( new NimbusLookAndFeel() ); MenuBarSample frame = new MenuBarSample(); frame.setVisible(true); } } |
mnuNew
associé au texte "New File"
) possède un gestionnaire d'événement.
Je vous laisse la responsabilité d'ajouter les gestionnaires d'événements associés aux autres éléments de menu.
Améliorations / Corrections
Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.
Emplacement :
Description des améliorations :