JMenuBar - Part 3

Accelerators and mnemonics are a big part of a GUI, you just don't know them by these names.

A mnemonic is a key-press that opens a JMenu or selects a MenuItem when the menu is opened.
An accelerator is a key-press that selects an option within the menu without it ever being open.

So, for example, if we wanted to open the Starter Menu by pressing Alt-S...we would bind a mnemonic to it. If we wanted to select the soup in the starter menu using 'Alt+U' without having to use the menu at all, we would set an accelerator.

The purpose of all this is to let people who really know the program to access functions quickly, and let people that don't use a mouse (some don't!) access the MenuBar.

Let's see this in action. We will use the previous example with all the Event Listeners in it.

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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.Color;
import java.awt.event.*;

// Class implements three different types of listener.
public class MenuBarExample_UltraExtended implements  ActionListener, ItemListener{

    JTextArea whitebox;
    JCheckBoxMenuItem cake, sorbet;
    
    public Container createContentPane()
    {
        whitebox = new JTextArea();
        whitebox.setEditable(false);
        whitebox.setLineWrap(true);
        whitebox.setWrapStyleWord(true);
        whitebox.setMinimumSize(new Dimension(300, 200));
        whitebox.setPreferredSize(new Dimension(300, 200));
        whitebox.setMaximumSize(new Dimension(300, 200));

        JPanel totalGUI = new JPanel();
        totalGUI.add(whitebox);
        
        totalGUI.setOpaque(true);
        return totalGUI;
    }

    public JMenuBar createMenuBar()
    {
        //Create the menu bar.
        JMenuBar menuBar = new JMenuBar();

        //Add a JMenu
        // The Mnemonic is S, but you need to press Alt+S to access it as it is a top level menu.
        JMenu starter = new JMenu("Starters");
        starter.setMnemonic(KeyEvent.VK_S);
        menuBar.add(starter);

        // Now we want to fill the menu.
        // This has every type of widget in the MenuBar
        // and has Event Listeners attached to each.
           
        // Sout with the Mnemonic 'U', and the Accelerator Alt+U
        JMenuItem soup = new JMenuItem("Soup");
        soup.setMnemonic(KeyEvent.VK_U);
        soup.setAccelerator(KeyStroke.getKeyStroke(
                            KeyEvent.VK_U, ActionEvent.ALT_MASK));
        soup.addActionListener(this);

        // Steak with the Mnemonic T
        JMenu steak = new JMenu("Steak");
        steak.setMnemonic(KeyEvent.VK_T);
           
        // Rare with the Mnemonic 'R', and the Accelerator Alt+R
        JMenuItem rare = new JMenuItem("Rare");
        rare.setMnemonic(KeyEvent.VK_R);
        rare.setAccelerator(KeyStroke.getKeyStroke(
                            KeyEvent.VK_R, ActionEvent.ALT_MASK));
        rare.addActionListener(this);
          
        // Well Done with the Mnemonic 'W', and the Accelerator Alt+W
        JMenuItem welldone = new JMenuItem("Well Done");
        welldone.setMnemonic(KeyEvent.VK_W);
        welldone.setAccelerator(KeyStroke.getKeyStroke(
                                KeyEvent.VK_W, ActionEvent.ALT_MASK));
        welldone.addActionListener(this);
           
        steak.add(rare);
        steak.add(welldone);

        // Chips with the Mnemonic 'C', Potato with the Mnemonic 'P'
        JRadioButtonMenuItem chips = new JRadioButtonMenuItem("Chips");
        chips.setMnemonic(KeyEvent.VK_C);
        chips.addActionListener(this);
        JRadioButtonMenuItem bp = new JRadioButtonMenuItem("Baked Potato");
        bp.setMnemonic(KeyEvent.VK_P);
        bp.addActionListener(this);

        // A button group to group the radiobuttons together.
        ButtonGroup sides = new ButtonGroup();
        sides.add(chips);
        sides.add(bp);

        // Cake with the Mnemonic 'k', Sorbet with the Mnemonic 'b'
        cake = new JCheckBoxMenuItem("Cake");
        cake.setMnemonic(KeyEvent.VK_K);
        cake.addItemListener(this);
        sorbet = new JCheckBoxMenuItem("Sorbet");
        sorbet.setMnemonic(KeyEvent.VK_B);
        sorbet.addItemListener(this);

        // Items added in the order you want them displayed.
        starter.add(soup);
        starter.addSeparator();
        starter.add(steak);
        starter.addSeparator();
        starter.add(chips);
        starter.add(bp);
        starter.addSeparator();
        starter.add(cake);
        starter.add(sorbet);

        return menuBar;
    }

    // Deals with the Action Events.
    public void actionPerformed(ActionEvent e)
    {
        whitebox.append(e.getActionCommand() + " Selected \n");
    }

    // Deals with the Item Events.
    public void itemStateChanged(ItemEvent e)
    {     
        if(e.getSource() == cake)
        {
            whitebox.append("Cake Clicked\n");
        }
        else if(e.getSource() == sorbet)
        {
            whitebox.append("Sorbet Clicked\n");
        }
    }

    private static void createAndShowGUI() {

        JFrame.setDefaultLookAndFeelDecorated(true);
        JFrame frame = new JFrame("[=] JMenuBar [=]");

        //Create and set up the ContentPane and MenuBar
        MenuBarExample_UltraExtended demo = new MenuBarExample_UltraExtended();
        
        frame.setContentPane(demo.createContentPane());
        frame.setJMenuBar(demo.createMenuBar());
        
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}
To see which keys you can bind to, have a look at the KeyEvent in the Java API. The best way to see how this works is to run the program, and navigate using only the keys. Alt-S opens the starters (as designated by an underline S). Any underline letter in a word designates a mnemonic that will navigate the menu. The accelerators are at the side of a menu item. If a menu item has an accelerator, you can access this without opening the menu using the accelerator.

Picture of MenuBar with Accelerator

So, for a Rare Steak, we press Alt+R without even opening the menu.
56
57
58
59
60
61
        // Rare with the Mnemonic 'R', and the Accelerator Alt+R
        JMenuItem rare = new JMenuItem("Rare");
        rare.setMnemonic(KeyEvent.VK_R);
        rare.setAccelerator(KeyStroke.getKeyStroke(
                            KeyEvent.VK_R, ActionEvent.ALT_MASK));
        rare.addActionListener(this);
Here we create our Menu Item. Then, we give it a mnemonic of R. Because we are in a menu, it automatically needs Alt pressed at the same time, so we don't need to put that in.
The accelerator is of two parts. We need to give it the key to press, along with the mask. The mask can be ALT_MASK, CTRL_MASK, SHIFT_MASK or META_MASK. A mask is needed so the command isn't carried out while you are typing. Line 59/60.

That's all you need to do, Swing does the rest for you. It is worth taking the time to define the shortcuts for your menu, as it gives it a easy touch of professionalism.

Back Top Next
Email Me
Code Style


Required Lessons

External Links

Created and Edited by Stuart Davidson
All Rights Reserved ©

Valid XHTML 1.0 Strict