UI Tutorial: JMenu


Summary:

Menus are an integral part of most any application.  They give a lot of options to the user with only a small amount UI “real estate” taken up.  With their compact size, problems with their small target for mouse clicks might occur, but these problems can be helped by adding hotkeys to frequently used menu items.

Where to Find It:

All the needed classes are found in the javax.swing library:

-         javax.swing.JMenu

-         javax.swing.JMenuBar

-         javax.swing.JMenuItem

The Basics:

Menus are a relatively easy object to add to your Java applications.  In this tutorial, you will learn how to do the following:

-         add JMenuBars to JFrames

-         add three types of menu items to the JMenus

o       Check box menu items

o       Radio button menu items

o       Normal text menu items

-         Listen for actions on the menu items you create

-         Check the status of menu items you create

-         Create “hot keys” for your menu items

-         Create tool tips for you menu item

-         Make sub-menus

The first thing you are going to need to do is declare your JMenuBar, JMenus and JMenuItems at the top of your class, most likely as private attributes. 

 

Declarations:

For the tutorial, here are the menu object declarations:

 

      private JMenuBar menuBar;

      private JLabel status;

 

      // Mock file menu //

      private JMenu file;

      private JMenuItem open;

      private JMenuItem save;

      private JMenuItem exit;

      private JCheckBoxMenuItem cbMenuItem;

      private JRadioButtonMenuItem rbMenuItem1;

      private JRadioButtonMenuItem rbMenuItem2;

      ////////////////////

     

      // Mock edit menu //

      private JMenu edit;

      private JMenuItem copy;

      private JMenuItem paste;

      ////////////////////

 

      // Just a plain menu //

      private JMenu etc;

      ///////////////////////

 

As you can see from the object names, this tutorial will have a File, Edit and etc. menu.  The menu items to be placed under the menus are also declared.

Menu Creation:

To create a menu, you have to:

1)      Instantiate your menu bar, menus and menu items and give them text to display:

 

            // Construct the file menu

            file = new JMenu("File");

            save = new JMenuItem("Save");

                 

 

2)      Add your menu items (and separator bars if needed) to their corresponding menus:

 

            file.add(open);

            file.add(save);

            file.addSeperator();

                 

 

3)      Add your menus to your menu bar:

 

            menuBar.add(file);

            menuBar.add(edit);

                       

 

4)      Add your menu bar to your frame:

 

            frame.setJMenuBar(makeMenuBar());

 

Capturing Clicks:

Now that seems easy enough right?  These 4 steps will get menus to show in your JFrame.  Now, to capture clicks on these menu items you will have to have an ActionListener.  JMenuItems work exactly like buttons, they actually inherit from AbstractButton.  This means that you can capture a click event on a menu item exactly like you would with a button.  For more in-depth information on how this works, please consult the JButton tutorial. 

 

Here is what is going on with actions in java.  Each object that can have an action performed to it (like a button with a click action) has different types of “ActionListeners” that “listen” to them.  The only thing special about these listeners is that they implement a method called “actionPerformed”.  This method will be invoked when an action happens. 

 

For example, we have a button.  We add a reference to an ActionListener class to this button.  With what we talked about so far, when the button gets clicked, it will go through all it’s references to ActionListeners (there can be more than one ActionListener attached to an object) and call their implementations of the actionPerformed() method. 

 

Now, a problem, if more than one object has the same ActionListener (which is almost always the case), how are you going to know which button was pushed when you get to the actionPerformed method of the listener because each button will do the same thing, call that method.  Here is the answer.  Objects with actions have a thing called an ActionCommand.  This is just a string that the object carries around with it and sends to the actionPerformed method once it gets clicked.  So just check that string when you get to the actionPerformed method to see what happened.  

 

Here is the way the action stuff is implemented in the tutorial code:

 

1)      Make your class implement ActionListener

 

public class MenuTutorial implements ActionListener{

 

2)      Add a method called “actionPerformed” and implement it accordingly

 

      public void actionPerformed(ActionEvent e){

            if(e.getActionCommand().equals("exit")){

                  System.exit(0);

            }else if(e.getActionCommand().equals("cb1")){

status.setText("CheckBox menu item is " + cbMenuItem.getState());

            }else{

                  status.setText(e.getActionCommand());

            }

      }

 

3)      Add the class as the action listener for each menu item

            save.addActionListener(this);

            open.addActionListener(this);

            exit.addActionListener(this);

                 

 

4)      Set the ActionCommand of each menu item.  This is the information that will be sent to the actionPerformed method when a click occurs.

 

            save.setActionCommand("Save Pressed");

            open.setActionCommand("Open Pressed");

            exit.setActionCommand("exit");

                 

 

Done.  Now we have menus items in menus in menu bars in frames with their actions being captured! 

Customization:

There are a few different types of menu items in the swing framework, the ones we will be using in the tutorial are JCheckBoxMenuItem and JRadioButtonMenuItem.  We will also be adding an “accelerator” or “hotkey” to a menu item (this can be done with any type of menu item). 

 

JCheckBoxMenuItem:

First we will tackle the easiest: the check box menu item.  This menu item work exactly like a normal text menu item.  The only difference is it has a checkbox to the left of it, and in the actionPerformed method after it is clicked, you can check the status of the check box by using the JCheckBoxMenuItem.getStatus() method.  This will return a Boolean saying weather or not the check box is checked.

 

      // Here is how to see if a JCheckBoxMenuItem

      // is checked or not

      status.setText("CheckBox menu item is " + cbMenuItem.getState());

 

JRadioButtonMenuItem:

Next, the JRadioButtonMenuItem.  This is a little bit tougher, because they usually come in sets of more than one where only one menu item can be selected at a time.  To accomplish this functionality, just put the menu items in a ButtonGroup:

 

      ButtonGroup bg = new ButtonGroup();

      rbMenuItem1 = new JRadioButtonMenuItem("Radio Button 1");

      rbMenuItem2 = new JRadioButtonMenuItem("Radio Button 2");

      bg.add(rbMenuItem1);

      bg.add(rbMenuItem2);

 

This will assure that only one radio button in the group is selected at a time.  Other than that, they function like normal text menu items.

 

Accelerator Keys:

Now, for adding an accelerator key.  First of all, an accelerator key is a key that can be pressed that will mimic a click on a menu item.  To add such a key to a menu item (of any type), you use the setAccelerator() method:

 

copy.setAccelerator(KeyStroke.getKeyStroke(

KeyEvent.VK_C, ActionEvent.CTRL_MASK));

 

In this code (pasted from the tutorial java file) we add an accelerator key of Cntl c to the copy menu item.  If the hot key was just going to be c, I could replace “keyEvent.VK_C, ActionEvent.CTRL_MASK” with simple ‘c’, but since the control button had to be pressed as well, the two parameter versions on KeyStroke.getKeyStroke() was needed.  This might seem cryptic and overcomplex, but it is really pretty simple.  The setAccelerator method looks for a key stroke event, so you return one from the getKeyStroke method.  The first parameter sets the key to press, the second (if needed) sets the “mask”, or what button would have to be pressed simultaneously with the first parameter key.

Best Practices:

When using menus, you should try to conform to standards. 

-         Use commonly seen menu names.  For example, if your application has files you can open or save, you should probably put those options under a menu named “File”, as seen in most applications. 

-         The exit button is usually placed under the file menu even though it does not have to do with files. 

-         Try to order your menus like others you may have seen.  File, Edit, …. Help is the general template for ordering. 

-         If you see your menu bar getting too long, try and make your categories more general and add submenus if necessary. 

-         Lastly, try and set your hotkeys according to your target OS’s standards.  If there is a copy menu item and your application will mostly be run on Windows PCs, you should set a hotkey “Ctrl c” for that menu item.

Things to Watch Out for When Including JMenus:

As stated above, if you have a large amount of JMenus, you should look into making them into submenus.  Also, if the JFrame they are in is resizable, making the window width smaller than the width of the JMenuBar can yield some unwanted results.

Limitations:

This Tutorial

This tutorial did not cover all that there is to cover on menus. If you are looking for a code sample a little more in depth, check the sun tutorial at: http://java.sun.com/docs/books/tutorial/uiswing/components/menu.html. It goes over things like icon menu items, setting mnemonics, laying out menus differently with box layouts, grid layouts, glue objects, etc.

JMenus

As for menus themselves, they are a great way to add a multitude of options, commands, etc. to your applications while only sacrificing minimal screen space. The only limitation I can think of is that users have a good idea of what a menu should be, so do not "muck" with the JMenu too much or it can quickly become confusing to a user. Mostly every computer user is familiar with using menus because they are so prevalent. Another down side to using menus might be their small target size for the mouse to click, but that is mitigated by the ability to use hotkeys. All in all, menus are great UI components, that’s why you see them at the top of most every application you might use.

References: