Richard G Baldwin (512) 223-4758, baldwin@austin.cc.tx.us, http://www2.austin.cc.tx.us/baldwin/

The AWT Package, Ordinary Menus

Java Programming, Lecture Notes # 140, Revised 01/27/98.

Preface

Students in Prof. Baldwin's Advanced Java Programming classes at ACC are responsible for knowing and understanding all of the material in this lesson.

Introduction

This series of lessons is concentrating on package java.awt where most of the functionality exists for providing the user interface to your application or applet.

We have learned how to handle events in JDK 1.1 and we have learned how to use the layout managers in JDK 1.1. These two topics form the basis for the design and implementation of a Graphical User Interface.

The next step is to take a look at the variety of components that are available to combine with layout and event handling to produce an effective Graphical User Interface.

The available components are defined by classes in the package java.awt. Our approach will be to group those classes into categories and study the material on a category basis. As of this writing, it looks as if the remaining categories are:

As things develop, I may find it necessary to modify these groupings.

Menus

The inheritance hierarchy for menus is as shown below.
 
java.lang.Object
        |
        +----MenuShortcut 
        |
        +----java.awt.MenuComponent 
                |
                +----java.awt.MenuBar
                |
                +----java.awt.MenuItem 
                        |
                        +----java.awt.Menu
                        |
                        +----java.awt.CheckboxMenuItem
                        |
                        +----java.awt.PopupMenu
As you might suspect from looking at this diagram, there are a number of interesting issues associated with menus, and we will investigate those issues in this and the next few lessons.

The first thing that we need to do is to take a very brief look at all the classes listed in the above hierarchy to get an overview of what lies ahead.

Our sample program in this lesson will make use of the Menu, MenuItem, MenuBar, and MenuShortcut classes. We will defer detailed consideration of the PopupMenu and CheckboxMenuItem classes until future lessons.

Before we look seriously at the four classes listed above, let's take a brief look at the MenuComponent class.

MenuComponent Class

According to the JDK 1.1 documentation, this class contains no fields, one public constructor, and about a dozen methods which are available to all subclasses of MenuComponent.

Although the JDK 1.1.3 documentation shows the constructor as
 
public MenuComponent()
this is apparently a typographical error. An attempt to instantiate an object of this class results in the following compiler error message:
 
junk.java:97: class java.awt.MenuComponent is an abstract class. It can't be instantiated. 
MenuComponent myMenu = new MenuComponent();
That being the case, lets move along to the classes that we will be using in this lesson.

Menu Class

The Menu class is used to construct what we typically think of as a pull-down menu. It provides no fields and the following public constructors. The behavior of the first two versions of the constructor are self-explanatory.

The third version has a boolean parameter referred to as tearOff in the detailed documentation. The following description from the JDK 1.1 documentation describes the use of the boolean parameter in the third version of the constructor.
 
"Constructs a new Menu with the specified label. If tearOff is true, the menu can be torn off - the menu will still appear on screen after the the mouse button has been released. NOTE: tear-off functionality may not be supported by all AWT implementations. If a particular implementation doesn't support tear-offs, this value will be silently ignored."
Because of this apparent uncertainty regarding support, we won't use this version of the constructor in this lesson.

There are more than a dozen methods provided by this class, and of course objects of this class also have access to the methods of the MenuComponent class and its superclasses. Some of the particularly interesting methods in this class are listed below:

Most of these methods are also self-explanatory and are used for creating and maintaining menus at runtime. We will be be using some of these methods in our sample program.

MenuItem Class

This class is used to instantiate objects which can become the choices in a menu. This class has no fields and the following public constructors: Although we haven't discussed MenuShortcut yet, probably anyone who has ever used a system with a Windows-style GUI is familiar with the use of shortcuts. For example, in the Netscape editor that I am using to produce this document, the keyboard shortcut for opening a file is Ctrl-O. When I open the File menu, the shortcut is displayed to the right of the main text on the menu item. If I enter Ctrl+O at the keyboard when the menu is not open, a dialog box appears that allows me to open a file.

This class provides about 20 methods, with some of the more interesting ones listed below:

The addActionListener() method is very familiar to us. Whenever a menu item is chosen using either the mouse or the keyboard shortcut, an ActionEvent is generated. In order to cause the selection of that menu item to cause a specific action, we will instantiate and register an ActionListener object which contains an overridden actionPerformed() method to produce the desired action. In the case of our sample program, the desired action will simply be to display the identification of the menu item that was selected. In a real program, the action would probably be more substantive.

MenuBar Class

According to the JDK 1.1 documentation, this is:
 
" A class that encapsulates the platform's concept of a menu bar bound to a Frame. In order to associate the MenuBar with an actual Frame, the Frame.setMenuBar() method should be called."
This class has no fields and the following public constructor: The class has about a dozen non-deprecated methods. An interesting subset of those methods is listed below: We will be using some of these methods in the sample program that follows.

MenuShortcut Class

This class is used to instantiate an object which represents a keyboard accelerator for a MenuItem. It has no fields and the following constructors: Apparently all of the shortcuts automatically require the user to hold down the Ctrl key while pressing another key. The boolean parameter in the second version of the constructor specifies whether or not the user will also have to hold down the Shift key as well (true means the Shift key is required).

According to the JDK 1.1 documentation, the first parameter shown as as int is:
 
"the raw keycode for this MenuShortcut, as would be returned in the keyCode field of a KeyEvent if this key were pressed"
Symbolic constants are defined in the KeyEvent class which define these raw key codes.

A small sampling of those symbolic constants, taken from the JDK 1.1 documentation, is shown below.
 
  • VK_8 
  • VK_9 
  • VK_A 
  • VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A) 
This class also provides five methods. We won't be using any of the methods in the sample programs in this lesson, but you would be well advised to go to the JDK 1.1 documentation and familiarize yourself with them.

Sample Program

This program is designed to be compiled and run under JDK 1.1

This application places two menus in a Frame object. One of the menus has two items and the other has three items.

The first item in the first menu also has a shortcut which is Ctrl+Shift+K.

When a menu item is selected, this generates an ActionEvent which in turn causes a line of text to be displayed on the screen identifying the item that was selected.

Typical screen outputs when menu items are selected using the mouse or the shortcut key are:
 
java.awt.MenuItem[menuitem4,label=Third Item on Menu B] 

java.awt.MenuItem[menuitem0,label=First Item on Menu A,shortcut=Ctrl+Shift+K]

A windowClosing() event listener object is instantiated and registered on the frame to terminate the program when the frame is closed.

The program was tested using JDK 1.1.3 running under Win95.

Interesting Code Fragments

There is quite a lot of repetitious code in this sample program due to the fact that essentially the same code is required to create each menu item and register a Listener object on it.

Also, the program generates two separate menus and essentially the same code is required for each. Therefore, in this section, we will be highlighting typical code fragments of the type required to perform each of the necessary operations.

Probably the most interesting thing about these code fragments is not the code itself, but rather the order in which the different operations are performed to accomplish the separate steps necessary to construct the menu. You should pay particular attention to the steps involved.

The first interesting code fragment instantiates a MenuShortcut object that will later be used in the instantiation of a MenuItem object.

Several such MenuItem objects will be added to a Menu object to produce a menu with several choices.

Two such Menu objects will be added to a MenuBar object to produce a menu bar with two separate menus.

The MenuBar object will then be associated with the Frame object.

Now that you have the overview, let's go back to the MenuShortcut object.

The argument list for the constructor in this case specifies a shortcut key combination consisting of Ctrl+Shift+K.

The true boolean parameter specifies the requirement for the Shift key.

The Ctrl key is apparently always required. The first parameter to the constructor is a symbolic constant defined in the KeyEvent class which specifies the "K" key.
 
MenuShortcut myShortcut = 
                     new MenuShortcut(KeyEvent.VK_K,true);
When this version of the constructor is used, the text string "Ctrl+Shift+K" is automatically placed on the menu item as an extension to the label provided by the programmer..

The next interesting code fragment is typical of that required to instantiate MenuItem objects which will later be added to the Menu object to create the actual menu. Two different styles of instantiation are shown. The first style specifies a shortcut for the item as discussed above. The second style does not specify a shortcut.
 
    MenuItem firstItemOnMenuA = 
          new MenuItem("First Item on Menu A",myShortcut);
    MenuItem secondItemOnMenuA = 
                    new MenuItem("Second Item on Menu A");
The next interesting code fragment instantiates an ActionListener object and registers it on two of the menu items. You have seen code of this type many times before. It is being included here simply to illustrate that associating ActionListener objects with menu items is no different from associating ActionListener objects with Button objects, or any other object capable of generating an ActionEvent.
 
    MyMenuProcessor myMenuProcessor = 
                                     new MyMenuProcessor();
    firstItemOnMenuA.addActionListener(myMenuProcessor);
    secondItemOnMenuA.addActionListener(myMenuProcessor);
The next code fragment is typical of that required to instantiate each of the two different Menu objects in this program and to add existing MenuItem objects to the Menu Object. This is a typical object.add() method invocation that you have seen many times in the past.
 
    Menu menuA = new Menu("Menu A");
    menuA.add(firstItemOnMenuA);
The next code fragment instantiates the MenuBar object and adds the two Menu objects to it.
 
   MenuBar menuBar = new MenuBar();
   menuBar.add(menuA);  
   menuBar.add(menuB);
At this point, we have created our two Menu objects and hooked them onto a MenuBar object. However, we haven't said anything about where the entire assembly will reside. We do this by associating the MenuBar object with a Frame object. Note that this is not accomplished using a typical object.add() method invocation. Rather, we will invoke a special method of the Frame class that has the following signature:
 
public synchronized void setMenuBar(MenuBar mb) 

Sets the menu bar for this frame to the specified menu bar. 

Parameters: mb - the menu bar being set 

The code that uses this method to set the menu bar for our Frame object follows:
 
Frame myFrame = new Frame("Copyright 1997, R.G.Baldwin");
myFrame.setMenuBar(menuBar);
That completes the new and interesting code in this program. The remaining code is similar to that which you have seen in many previous example programs. A complete listing of the program is provided in the next section.

Program Listing

This section contains a complete listing of the program. See the previous sections for an operational description of the program.
 
/*File Menu01.java Copyright 1997, R.G.Baldwin
This program is designed to be compiled and run under 
JDK 1.1

This application places two menus in a Frame object.  One
of the menus has two items and the other has three items.

The first item in the first menu also has a shortcut which
is Ctrl+Shift+K.

When a menu item is selected, this generates an Action 
event which in turn causes a line of text to be displayed
on the screen identifying the item that was selected.

Typical screen outputs when menu items are selected using
the Mouse are (line breaks manually inserted for this 
document).

java.awt.MenuItem[menuitem4,label=Third Item on Menu B]
java.awt.MenuItem[menuitem0,label=First Item on Menu A,
  shortcut=Ctrl+Shift+K]

A windowClosing() event listener object is instantiated 
and registered on the frame to terminate the program when
the frame is closed.

The program was tested using JDK 1.1.3 running under Win95.
**********************************************************/

import java.awt.*;
import java.awt.event.*;
//=======================================================//

public class Menu01 {
  public static void main(String[] args){
    GUI gui = new GUI();//instantiate a GUI
  }//end main
}//end class Menu01
//=======================================================//

class GUI {
  public GUI(){//constructor
    //Instantiate a MenuShortcut object
    MenuShortcut myShortcut = 
                      new MenuShortcut(KeyEvent.VK_K,true);
  
    //Instantiate several MenuItem objects  
    MenuItem firstItemOnMenuA = 
           new MenuItem("First Item on Menu A",myShortcut);
    MenuItem secondItemOnMenuA = 
                     new MenuItem("Second Item on Menu A");
    MenuItem firstItemOnMenuB = 
                      new MenuItem("First Item on Menu B");
    MenuItem secondItemOnMenuB = 
                     new MenuItem("Second Item on Menu B");
    MenuItem thirdItemOnMenuB = 
                      new MenuItem("Third Item on Menu B");
  
    //Instantiate an ActionListener object and register 
    // it on the MenuItem objects.  
    MyMenuProcessor myMenuProcessor = 
                                     new MyMenuProcessor();
    firstItemOnMenuA.addActionListener(myMenuProcessor);
    secondItemOnMenuA.addActionListener(myMenuProcessor);
    firstItemOnMenuB.addActionListener(myMenuProcessor);
    secondItemOnMenuB.addActionListener(myMenuProcessor);
    thirdItemOnMenuB.addActionListener(myMenuProcessor);
    
    //Instantiate two Menu objects and add the MenuItem
    // objects to them
    Menu menuA = new Menu("Menu A");
    menuA.add(firstItemOnMenuA);
    menuA.add(secondItemOnMenuA);
  
    Menu menuB = new Menu("Menu B");
    menuB.add(firstItemOnMenuB);
    menuB.add(secondItemOnMenuB);
    menuB.add(thirdItemOnMenuB);  
    
    //Instantiate a MenuBar object and add the Menu 
    // objects to it  
    MenuBar menuBar = new MenuBar();
    menuBar.add(menuA);  
    menuBar.add(menuB);
  
    //Instantiate a Frame object and associate the MenuBar
    // object with the Frame object.  Note that this is 
    // NOT a typical myFrame.add() method invocation, but
    // rather is a special form of method invocation that
    // is required to associate a MenuBar object with a 
    // Frame object.
    Frame myFrame = 
                  new Frame("Copyright 1997, R.G.Baldwin");
    //note that this is not an add method
    myFrame.setMenuBar(menuBar);
    myFrame.setSize(250,100);
    myFrame.setVisible(true);

    //Instantiate and register a window listener to 
    // terminate the program when the Frame is closed. 
    myFrame.addWindowListener(new Terminate());
  }//end constructor
}//end class GUI definition
//=======================================================//

//Class to instantiate an ActionListener object to be 
// registered on the menu items.
class MyMenuProcessor implements ActionListener{
  public void actionPerformed(ActionEvent e){
    //Display the menu item that generated the ActionEvent
    System.out.println(e.getSource());
  }//end actionPerformed
}//end class MyMenuProcessor
//=======================================================//

class Terminate extends WindowAdapter{
  public void windowClosing(WindowEvent e){
    System.exit(0);//terminate the program 
  }//end windowClosing
}//end class Terminate
//=======================================================//
-end-