Previous | Next | Trail Map | Creating a User Interface | Using the JFC/Swing Packages

How to Use Menus

A menu provides a space-saving way to let the user choose one of several options. Other components with which the user can make a one-of-many choice include combo boxes, lists, radio buttons, and tool bars. If any of your menu items performs an action that is duplicated by another menu item or by a tool-bar button, then in addition to this section you should read How to Use Actions.

Menus are unique in that, by convention, they aren't placed with the other components in the UI. Instead, a menu usually appears either in a menu bar or as a popup menu. A menu bar contains one or more menus and has a customary, platform-dependent location -- usually along the top of a window. A popup menu is a menu that is invisible until the user makes a platform-specific mouse action, such as pressing the right mouse button, over a popup-enabled component. The popup menu then appears under the cursor.

The following figure shows the Swing components that implement each part of the menu system.

[PENDING: Labels to add: JMenuBar, JMenu, JMenuItem, JCheckBoxMenuItem, JRadioButtonMenuItem, JSeparator. Leave out JPopupMenu. When shortcuts work again, show them.]

The rest of this section teaches you about the menu components and tells you how to use various menu features:

The Menu Component Hierarchy

Here is a picture of the inheritance hierarchy for the menu-related classes:
                     Object
                        |
                    Component
                        |
                    Container
                        |
                    JComponent                
                        |
    +---------+---------+---+---------------+
    |         |             |               |
JMenuBar  JPopupMenu  JAbstractButton  JSeparator
                            |
                        JMenuItem
                            |
   +-----------+------------+------+
   |           |                   |
JMenu  JCheckBoxMenuItem  JRadioButtonMenuItem
As the figure shows, menu items (including menus) are simply buttons. You might be wondering how a menu, if it's only a button, shows its menu items. The answer is that when a menu is activated, it automatically brings up a popup menu that displays the menu items.

Creating Menus

Here is the code that created the menus shown near the beginning of this menu section. You can find the entire program in MenuLookDemo.java. To run the program, you need to have the following image file: images/middle.gif image file. Because this code has no event handling, the menus do nothing useful except look like they should. If you run the example, you'll notice that despite the lack of custom event handling, menus and submenus appear when they should, and the check boxes and radio buttons respond appropriately when the user chooses them.
//in the constructor for a JFrame subclass:
JMenuBar menuBar;
JMenu menu, submenu;
JMenuItem menuItem;
JCheckBoxMenuItem cbMenuItem;
JRadioButtonMenuItem rbMenuItem;
...
//Create the menu bar.
menuBar = new JMenuBar();
setJMenuBar(menuBar);

//Build the first menu.
menu = new JMenu("A Menu");
menuBar.add(menu);

//a group of JMenuItems
menuItem = new JMenuItem("A text-only menu item");
menu.add(menuItem);
menuItem = new JMenuItem("Both text and icon", 
new ImageIcon("images/middle.gif"));
menu.add(menuItem);
menuItem = new JMenuItem(new ImageIcon("images/middle.gif"));
menu.add(menuItem);

//a group of radio button menu items
menu.addSeparator();
ButtonGroup group = new ButtonGroup();
rbMenuItem = new JRadioButtonMenuItem("A radio button menu item");
rbMenuItem.setSelected(true);
group.add(rbMenuItem);
menu.add(rbMenuItem);
rbMenuItem = new JRadioButtonMenuItem("Another one");
group.add(rbMenuItem);
menu.add(rbMenuItem);

//a group of check box menu items
menu.addSeparator();
cbMenuItem = new JCheckBoxMenuItem("A check box menu item");
menu.add(cbMenuItem);
cbMenuItem = new JCheckBoxMenuItem("Another one");
menu.add(cbMenuItem);

//a submenu
menu.addSeparator();
submenu = new JMenu("A submenu");
menuItem = new JMenuItem("An item in the submenu");
submenu.add(menuItem);
menuItem = new JMenuItem("Another item");
submenu.add(menuItem);
menu.add(submenu);

//Build second menu in the menu bar.
menu = new JMenu("Another Menu");
menuBar.add(menu);

As the code shows, to set the menu bar for a JFrame, you use the setJMenuBar method. To add a JMenu to a JMenuBar, you use the add(JMenu) method. To add menu items and submenus to a JMenu, you use the add(JMenuItem) method. These methods and more are listed in The Menu API.

Handling Events from Menu Items

To detect when the user selects a JMenuItem, you can listen for action events (just as you would for a JButton). To detect when the user selects a JRadioButtonMenuItem, you can listen for either action events or item events, as described in How to Use Radio Buttons. For JCheckBoxMenuItems, you generally listen for item events, as described in How to Use Check Boxes.

The following picture shows a program that adds event detection to the preceding example. The program's code is in MenuDemo.java. Like MenuLookDemo, MenuDemo uses the images/middle.gif image file.

Here is the code that implements the event handling:
public class MenuDemo ... implements ActionListener, ItemListener {
    ...
    public MenuDemo() {
        ...//for each JMenuItem instance:
        menuItem.addActionListener(this);

        ...//for each JRadioButtonMenuItem: 
        rbMenuItem.addActionListener(this);

        ...//for each JCheckBoxMenuItem: 
        cbMenuItem.addItemListener(this);
        ...
    }

    public void actionPerformed(ActionEvent e) {
        ...//Get information from the action event...
        ...//Display it in the text area...
    }

    public void itemStateChanged(ItemEvent e) {
        ...//Get information from the item event...
        ...//Display it in the text area...
    }
For examples of handling action and item events, see the button, radio button, and check box sections, as well as the list of examples at the end of this section.

Bringing Up a Popup Menu

To bring up a popup menu, you must register a mouse listener on each component that the popup menu should be associated with. The mouse listener must detect user requests that the popup menu be brought up. For Windows and Motif platforms, the user brings up a popup menu by pressing the right mouse button while the cursor is over a component that has a popup menu.

The mouse listener brings up the popup menu by invoking setVisible(true) (or show()) on the appropriate JPopupMenu instance. Here is an example of the code to use: [PENDING: Check. This is the code used for 1.1 AWT popup menus. Is it appropriate to use the same code for Metal popup menus?]

    ...//where the GUI is constructed:
    //Listen for when the popup menu should be shown.
    MouseListener listener = new PopupListener();
    //Add the mouse listener to every component over which
    //the popup menu can appear:
    contentPane.addMouseListener(listener);
    output.addMouseListener(listener);
}

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

Popup menus have a few interesting implementation details. One is that popup menus are used to display all menus. When any menu is activated, it uses a popup menu to show its menu items.

Another detail is that a popup menu itself uses another component to implement the window containing the menu items. Depending on the circumstances under which the popup menu is displayed, the popup menu might implement its "window" using a lightweight component (such as a JPanel), a "mediumweight" component (such as a Panel(in the Creating a User Interface trail)), or a heavyweight window ( Window(in the API reference documentation)).

Lightweight popup windows are more efficient than heavyweight windows, but they don't work well if you have any heavyweight components inside your GUI. Specifically, when the lightweight popup's display area intersects the heavyweight component's display area, then the heavyweight component is drawn on top. This is one of the reasons we recommend against mixing heavyweight and lightweight components. If you absolutely need to use a heavyweight component in your GUI, then you can use the JPopupMenu setLightWeightPopupEnabled method to disable lightweight popup windows. For details, see Mixing Heavy and Light Components, an article in The Swing Connection.

Customizing Menu Layout

Because menus are made up of ordinary Swing components, you can easily customize them. For example, you can add any lightweight component to a JMenu or JMenuBar. And because JMenuBar uses BoxLayout, you can customize a menu bar's layout just by adding invisible components to it. Here is an example of adding a glue component to a menu bar, so that the last menu is at the right edge of the menu bar:

...//create and add some menus...
menuBar.add(Box.createHorizontalGlue());
...//create the rightmost menu...
menuBar.add(rightMenu);
Here is a picture of the result, which you can duplicate by compiling and running MenuGlueDemo.java:

Another way of changing the look of menus is to change the layout managers used to control them. For example, you can change a menu bar's layout manager from the default left-to-right BoxLayout to something such as GridLayout. You can also change how an activated menu or other popup menu lays out its items, as MenuLayoutDemo.java demonstrates. Here's a picture of the menu layout that MenuLayoutDemo creates:

The Menu API

[PENDING: Put tables here]

Examples that Use Menus

Menus are used in a few Swing examples.

Example Where Described Notes
MenuLookDemo.java This section (Creating Menus) A simple example that creates all kinds of menus except popup menus, but doesn't handle events from the menu items.
MenuDemo.java This section (Handling Events from Menu Items) Adds event handling to MenuLookDemo.
MenuGlueDemo.java This section (Customizing Menu Layout) Demonstrates affecting menu layout by adding an invisible components to the menu bar.
MenuLayoutDemo.java This section (Customizing Menu Layout) Implements sideways-opening menus arranged in a vertical menu bar.
ActionDemo.java How to Use Actions Uses Action objects to implement menu items that duplicate functionality provided by tool bar buttons.
Framework.java [PENDING: nowhere yet; may go away]
InternalFrameDemo.java How to Use Internal Frames Uses a menu item to create windows.


Previous | Next | Trail Map | Creating a User Interface | Using the JFC/Swing Packages