Chapter 20

Menus, Buttons, and Dialong Boxes


CONTENTS


This chapter covers the details of using the Menu, Button, and Dialog classes. It describes the available menu and button options and shows you how to quickly and easily construct menus and buttons for your window programs. The use of dialog boxes is explained, and a generic MessageDialog component is constructed and explained as part of an example. When you finish this chapter, you will be able to effectively use menus, buttons, and dialog boxes in your Java window programs.

Adding Menus to Windows

Java provides a rich set of menu-related classes to create and interact with pull-down menus. The MenuComponent class is the superclass of all menu-related classes. It extends the Object class. The getFont() and setFont() methods are the most useful methods provided by MenuComponent. Its two direct superclasses, MenuBar and MenuItem, provide most of the methods for creating and using menus. The CheckboxMenuItem class extends the MenuItem class and supports menu items that can be checked on or off. The Menu class extends the MenuItem class and implements a collection of MenuItem objects that can be assigned to a MenuBar object.

You are probably somewhat familiar with menus from Chapters 18, "Opening Windows," and 19, "Organizing Window Programs." A program's application window is implemented by a Frame object. It can have one and only one MenuBar object, which is set using the setMenuBar() method. A menu bar is a collection of menus. Each menu is represented as a separate pull-down menu on the menu bar. Common examples are the File, Edit, and Help pull-down menus found in many window applications. The MenuBar class allows a special menu to be designated as a Help menu, but this feature is not implemented in Windows 95 or NT.

A Menu object contains one or more MenuItem objects, which can be a normal user-selectable MenuItem object, a CheckboxMenuItem object, or another Menu object. Java supports tear-off menus, which are menus that can be removed from a menu bar. A tear-off menu is constructed in the same manner as a regular menu-you only need to set the boolean tear-off value in the Menu() constructor. Tear-off menus, however, are not implemented within Windows 95 or NT.

The MenuItem class is the superclass of the Menu class. It allows a menu to be a menu item and is used in constructing cascading, multilevel menus. MenuItem is also the superclass of the CheckboxMenuItem class and provides the capability to implement menu items that can be checked or unchecked. If a MenuItem object is constructed directly with the MenuItem constructor, it becomes a normal menu item that is selected from a pull-down menu.

The MyMenu Class

The creation and organization of menu bars, menus, and menu items into a program's menu is a straightforward, but tedious, process. You have to create a menu bar, create and add menus to the menu bar, add menu items to the menus, and then add the menu bar to the program's application window. This usually involves the use of a large number of constructors and access methods. To illustrate the use of the menu-related classes and to simplify the menu-creation process, you'll create two classes, MyMenu and MyMenuBar, that can be used to quickly construct menus for Java programs. These classes implement multiple levels of menus, checkbox menu items, and menu-disabling options. The special Help menu and tear-off menus are not implemented, however, because they are transparent to Windows 95 and NT.

The MyMenu class is used to construct menus using an array of objects consisting of String objects that represent menu labels, or arrays of objects that represent submenus. Menu labels can be either checkbox menu items or normal menu items and can be either initially enabled or disabled (grayed out). Checkbox menu items can be initially checked or unchecked. The first character of the label's text string is used to indicate what type of label it is. The character conventions are as follows:

+
A checkbox menu item that is initially checked and enabled.
#
A checkbox menu item that is initially checked and disabled.
-
A checkbox menu item that is initially unchecked and enabled. If the label consists of just -, it indicates a separator.
=
A checkbox menu item that is initially unchecked and disabled.
~
A normal menu item that is initially disabled.
  Any other character indicates a normal, enabled menu item. If the first character is !, it is ignored. This allows any menu item to begin with any character.

These conventions apply to menu options. Only the ~ and ! options are used with the menu's main label. Using these options greatly simplifies the process of a menu creation. The source code for the MyMenu class is shown in Listing 20.1.


Listing 20.1. The source code of the MyMenu class.

package jdg.ch20;

import java.awt.*;

public class MyMenu extends Menu {
 public MyMenu(Object labels[]) {
  super((String)labels[0]);
  String menuName = (String) labels[0];
  char firstMenuChar = menuName.charAt(0);
  if(firstMenuChar == '~' || firstMenuChar =='!'){
   setLabel(menuName.substring(1));
   if(firstMenuChar == '~') disable();
  }
  for(int i=1;i<labels.length;++i) {
   if(labels[i] instanceof String){
    if("-".equals(labels[i])) addSeparator();
    else{
     String label = (String)labels[i];
     char firstChar = label.charAt(0);
     switch(firstChar){
     case '+':
      CheckboxMenuItem checkboxItem = new CheckboxMenuItem(label.substring(1));
      checkboxItem.setState(true);
      add(checkboxItem);
      break;
     case '#':
      checkboxItem = new CheckboxMenuItem(label.substring(1));
      checkboxItem.setState(true);
      checkboxItem.disable();
      add(checkboxItem);
      break;
     case '-':
      checkboxItem = new CheckboxMenuItem(label.substring(1));
      checkboxItem.setState(false);
      add(checkboxItem);
      break;
     case '=':
      checkboxItem = new CheckboxMenuItem(label.substring(1));
      checkboxItem.setState(false);
      checkboxItem.disable();
      add(checkboxItem);
      break;
     case '~':
      MenuItem menuItem = new MenuItem(label.substring(1));
      menuItem.disable();
      add(menuItem);
      break;
     case '!':
      add(label.substring(1));
      break;
     default:
      add(label);
     }
    }
   }else{
    add(new MyMenu((Object[])labels[i]));
   }
  }
 }
 public MenuItem getItem(String menuItem) {
  int numItems = countItems();
  for(int i=0;i<numItems;++i)
   if(menuItem.equals(getItem(i).getLabel())) return getItem(i);
  return null;
 }
}


The MyMenu class specifies that it is in the package jdg.ch20. Make sure that you place it in the jdg/ch20 directory and compile it. You'll be using it quite a bit in subsequent chapters.

MyMenu contains no field variables. It consists of a single constructor and the getItem() access method. The getItem() method retrieves a menu item contained in the menu and based on the menu item's label. It uses the countItems() and getItem() methods of the Menu class to retrieve the menu items contained in a menu and the getLabel() method of the MenuItem class to match a menu item with the search string.

The MyMenu constructor constructs a menu from an array of menu labels and nested menu arrays (representing submenus). For example, to construct a typical File menu, labeled File, with the New and Open menu items followed by a separator and an Exit menu item, you would use the following MyMenu constructor:

String fileMenuLabels[] = {"File","New","Open","-","Exit"};
MyMenu fileMenu = new MyMenu(fileLabelMenus);

The first object in the array must be a String object that is the main label associated with the menu. The following objects are either String objects identifying the labels of the menu items contained in the menu, separators, or second-level arrays representing submenus. For example, the following creates a multilevel menu:

String goMenuLabels[] = {"Go","Beginning","End","Previous","Next"};
String editMenuLabels[] = {"Edit","Copy","Cut","-","Paste","-",goMenuLabels};
MyMenu editLabel = new MyMenu(editMenuLabels);

Using the MyMenu class is much easier than constructing each of the individual menu items and adding them to a menu.

Let's step through the MyMenu constructor to see how it works. It uses the super() class constructor call statement to construct a Menu object using the first label in the labels[] array. This label may contain the ~ or ! character as the first character. MyMenu() checks for these characters and readjusts the menu's label accordingly. If the first character of the menu's label is ~, MyMenu() will disable the entire menu using the disable() method of the MenuItem class.

After setting up the menu's main label, MyMenu() iterates through the list of objects contained in labels[]. If the object is an instance of the String class, and is therefore a label, MyMenu() checks the first letter of the label and processes it accordingly. If the object is not an instance of the String class, MyMenu() calls itself again, passing the object to itself as another array of objects. It then adds the resulting MyMenu object to itself using the add() method of the Menu class. This allows submenus to be processed in a recursive fashion.

MyMenu() processes the menu item labels by using a switch statement to check the first character of the label to see if it matches the +, #, -, =, ~, or ! character. If it does not match any of these characters, the label is added as a normal menu item. If the label equals -, a separator is added.

If the first character is +, an enabled and checked CheckboxMenuItem object is added to the menu. The setState() method of the CheckboxMenuItem class is used to set the state of the menu item to checked. If the first character is #, a checked, but disabled, CheckboxMenuItem object is added. The disable() method of the MenuItem class is used to disable the menu item. The cases in which the first character of the label is - or = are processed in a similar manner, except that the CheckboxMenuItem object is initially unchecked.

When the first character of the label is ~, a normal MenuItem object is added to the menu. The menu item is disabled.

The ! character is an escape character that is used to create a normal menu item beginning with any of the special characters previously mentioned. When the first character of a label is !, the actual label generated begins with the subsequent character.

The MyMenuBar Class

The MyMenuBar class uses the MyMenu class presented in the previous section to quickly create an entire menu bar. Whereas the MyMenu class uses an array of labels and submenus to create a menu, the MyMenuBar class uses an array of these arrays to create the entire menu bar. For example, the following statements will construct a menu bar with File, Edit, and Help menus, each consisting of individual menu items:

String menuBarLabels[] = {

 {"File","New","Open","-","~Save As","-","Exit"};
 {"Edit","Copy","Cut","-","~Paste"};
 {"Help","Index"};
};
MyMenuBar menuBar = new MyMenuBar(menuBarLabels);

Note that the Save As and Paste menu items are initially disabled.

The source code of the MyMenuBar class is shown in Listing 20.2.


Listing 20.2. The source code of the MyMenuBar class.

package jdg.ch20;

import java.awt.*;

public class MyMenuBar extends MenuBar {
 public MyMenuBar(Object labels[][]) {
  super();
  for(int i=0;i<labels.length;++i)
   add(new MyMenu(labels[i]));
 }
 public MyMenu getMenu(String menuName) {
  int numMenus = countMenus();
  for(int i=0;i<numMenus;++i)
   if(menuName.equals(getMenu(i).getLabel())) return((MyMenu)getMenu(i));
  return null;
 }
}


The MyMenuBar constructor simply iterates through the outer array and passes the first-level elements (which are themselves Object arrays) to the MyMenu constructor to construct MyMenu objects. These objects are then added to the MyMenuBar object being constructed using the add() method inherited from the MenuBar class.

The getMenu() method retrieves a MyMenu object from a MyMenuBar object based on the label associated with the MyMenu object. It uses the CountMenus() and getMenu() methods of the MenuBar class to retrieve each MyMenu object contained in the menu bar. The getLabel() method of the MenuItem class is used to check the labels of the MyMenu objects against the search string.

The MenuApp Program

The MenuApp program illustrates the use of the MyMenuBar and MyMenu classes. Its source code is shown in Listing 20.3.


Listing 20.3. The source code of the MenuApp program.

import java.awt.*;
import jdg.ch20.MyMenu;
import jdg.ch20.MyMenuBar;

public class MenuApp extends Frame {
 MyMenuBar menuBar;
 public static void main(String args[]){
  MenuApp app = new MenuApp();
 }
 public MenuApp() {
  super("Menu Madness");
  setup();
  pack();
  resize(400,400);
  show();
 }
 void setup() {
  setBackground(Color.white);
  setupMenuBar();
 }
 void setupMenuBar(){
  String gotoMenu[] = {"Go To","Beginning","End","-","Line Number"};
  Object menuItems[][] = {
   {"File","New","Open","-","~Save","~Save As","-","Exit"},
   {"Edit","Copy","Cut","-","~Paste"},
   {"Search","Find","~Find Next","~Find Previous","-", gotoMenu},
   {"View","-Hex","+Line Number","+Column Number"},
   {"Help","About Menu Madness"},
  };
  menuBar = new MyMenuBar(menuItems);
  setMenuBar(menuBar);
 }
 public boolean handleEvent(Event event) {
  if(event.id==Event.WINDOW_DESTROY){
   System.exit(0);
   return true;
  }else if(event.id==Event.ACTION_EVENT){
   if(event.target instanceof MenuItem){
    if("Exit".equals(event.arg)){
     System.exit(0);
     return true;
    }else if("New".equals(event.arg) || "Open".equals(event.arg)){
     menuBar.getMenu("File").getItem("Save").enable();
     menuBar.getMenu("File").getItem("Save As").enable();
     return true;
    }else if("Copy".equals(event.arg) || "Cut".equals(event.arg)){
     menuBar.getMenu("Edit").getItem("Paste").enable();
     return true;
    }else if("Find".equals(event.arg)){
     menuBar.getMenu("Search").getItem("Find Next").enable();
     menuBar.getMenu("Search").getItem("Find Previous").enable();
     return true;
    }else if("Hex".equals(event.arg)){
     CheckboxMenuItem hexMenuItem =
      (CheckboxMenuItem) menuBar.getMenu("View").getItem("Hex");
     CheckboxMenuItem lineMenuItem =
      (CheckboxMenuItem) menuBar.getMenu("View").getItem("Line Number");
     CheckboxMenuItem colMenuItem =
      (CheckboxMenuItem) menuBar.getMenu("View").getItem("Column Number");
     boolean hexState = hexMenuItem.getState();
     lineMenuItem.setState(!hexState);
     colMenuItem.setState(!hexState);
     return true;
    }else if("Line Number".equals(event.arg) ||
     "Column Number".equals(event.arg)){
     CheckboxMenuItem hexMenuItem =
      (CheckboxMenuItem) menuBar.getMenu("View").getItem("Hex");
     CheckboxMenuItem lineMenuItem =
      (CheckboxMenuItem) menuBar.getMenu("View").getItem("Line Number");
     CheckboxMenuItem colMenuItem =
      (CheckboxMenuItem) menuBar.getMenu("View").getItem("Column Number");
     boolean lineState = lineMenuItem.getState();
     boolean columnState = colMenuItem.getState();
     hexMenuItem.setState(!(lineState | columnState));
     return true;
    }else if("About Menu Madness".equals(event.arg)){
     menuBar.getMenu("Help").disable();
     return true;
    }
   }
  }
  return false;
 }
}


MenuApp shows how the MyMenuBar and MyMenu classes are used to easily create a menu bar and to support the processing of menu-related events. When the program is executed, it displays a blank opening screen and a menu bar with five pull-down menus, as shown in Figure 20.1.

Figure 20.1 : The MenuApp opening window.

Click on the File menu and select the New menu item as shown in Figure 20.2. This will cause the Save and Save As menu items to become enabled. You can verify this by clicking on the File menu once again.

Figure 20.2 : The File menu.

Click on the Edit menu and select the Copy menu item as shown in Figure 20.3. This results in the Paste menu item becoming enabled.

Figure 20.3 : The Edit menu.

Click on the Search menu and then on the Go To menu item as shown in Figure 20.4. The Go To menu item is a second-level menu that is attached to the Search menu.

Figure 20.4 : The Search menu.

Click on the View menu and select the Hex checkbox menu item as shown in Figure 20.5. Notice that the Line Number and Column Number menu items that are initially checked become unchecked, as shown in Figure 20.6.

Figure 20.5 : The View menu.

Figure 20.6 : The View menu after checking Hex.

Click on the Help menu and select About Menu Madness, as shown in Figure 20.7. This Help menu isn't much help at all because it is programmed to disable itself, as shown in Figure 20.8.

Figure 20.7 : The Help Menu.

Figure 20.8 : The Help menu disabled.

You've completed the tour of the MenuApp program. Select Exit from the File menu to terminate the program's operation.

Inside MenuApp

The MenuApp class consists of a single field variable, menuBar, that is an object of class MyMenuBar. The MenuApp constructor creates a 400¥400 frame window with the title Menu Madness and invokes the setup() method to set up the background color and the menu bar. The setup() method invokes setupMenuBar() to actually perform the menu bar setup.

The setupMenuBar() method creates a gotoMenu[] array as the labels of a submenu that will be attached to the Search menu. The menuItems[][] array is used to define the labels associated with the menu bar and its first-level menus. The gotoMenu[] array is included as an object in this array. Notice the use of the first-character conventions for disabling menu items and specifying menu items that are checkboxes. The menu bar is created, assigned to the menuBar variable, and set as the menu bar for the MenuApp frame.

Creating the menu bar was a snap using the MyMenuBar class. However, creating the menu bar is only half the work. You also need to write event-handling code that acts on the menu items selected by the user. The event-handling code of MenuApp is used to illustrate the use of the various methods provided with menus and menu items.

The WINDOWS_DESTROY event and the Exit menu item are handled by terminating the program's execution. The New and Open menu items cause the Save and Save As menu items to be enabled. The getMenu() method of MyMenuBar and the getItem() method of MyMenu are used to retrieve the Save and Save As MenuItem objects. The enable() method of the MenuItem class is used to enable these menu items. Note that the Save and Save As menu items, as well as some other menu items, are not handled. Selecting these menu items results in no action being performed by MenuApp.

The Copy and Cut menu items are processed in a similar manner as the New and Open menu items. Selecting Copy or Cut menu items results in the Paste menu item being enabled.

The Find menu item causes the Find Next and Find Previous menu items to be enabled.

The Hex checkbox menu item is handled by using the getState() method to determine the state of its associated checkbox and then setting the checkbox state of the Line Number and Column Number checkbox menu items to the opposite state.

The Line Number and Column Number menu items are set and reset independent of each other, but they are combined to determine the state of the Hex menu item. If both the Line Number and Column Number menu items are unchecked, the state of the Hex menu item is set to checked. Otherwise, the Hex menu item is set to unchecked.

The handling of the About Menu Madness menu item shows how an entire menu can be disabled.

Working with Buttons

Buttons are one of the easiest GUI components to use in a Java window program. You create them using the Button constructor and add them to your program using the add() method of their container. After that, you just handle the events associated with them and, optionally, change their labels.

The ButtonBar Class

To do something a little bit creative with labels, you can design a ButtonBar class. This class creates a dialog box with a specified label and adds a list of buttons to the dialog box, in the form of a button bar. It also allows the buttons in the button bar to be arranged in a vertical or horizontal fashion. The source code for the ButtonBar class is shown in Listing 20.4.


Listing 20.4. The source code of the ButtonBar class.

package jdg.ch20;

import java.awt.*;

public class ButtonBar extends Dialog {
 public static int HORIZONTAL = 0;
 public static int VERTICAL = 1;
 public ButtonBar(Frame parent,String title,String labels[],int orientation) {
  super(parent,title,false);
  int length = labels.length;
  if(orientation == HORIZONTAL) setLayout(new GridLayout(1,length));
  else setLayout(new GridLayout(length,1));
  for(int i=0;i<length;++i) add(new Button(labels[i]));
  pack();
  resize(minimumSize());
 }
 public boolean handleEvent(Event event) {
  if(event.id==Event.WINDOW_DESTROY) show(false);
  return false;
 }
}


The HORIZONTAL and VERTICAL constants are used to specify the orientation of the button bar. The constructor uses the parent, title, labels[], and orientation parameters. The parent and title parameters are passed to the Dialog class constructor via the super() constructor call statement. The false value indicates that the button bar is not modal. The orientation parameter is used to determine the type of GridLayout associated with the button bar. After the orientation is specified, the Button objects, whose labels are specified by the labels[] array, are added to the button bar. The button bar dialog box is then packed and resized to the minimum size needed to contain the buttons.

A single event is handled by the ButtonBar class. The WINDOWS_DESTROY event is generated when a user tries to close the button bar dialog box. When this happens, the show() method inherited from the Window class is used to hide the dialog box. The handleEvent() method returns the false value, allowing the event to be processed by the window containing the dialog box.

The ButtonApp Program

The ButtonApp program illustrates the operation of the ButtonBar class. Its source code is shown in Listing 20.5.


Listing 20.5. The source code of the ButtonApp program.

import java.awt.*;
import jdg.ch20.MyMenu;
import jdg.ch20.MyMenuBar;
import jdg.ch20.ButtonBar;

public class ButtonApp extends Frame {
 MyMenuBar menuBar;
 ButtonBar buttonBar;
 public static void main(String args[]){
  ButtonApp app = new ButtonApp();
 }
 public ButtonApp() {
  super("ButtonApp");
  setup();
  pack();
  resize(400,400);
  show();
 }
 void setup() {
  setBackground(Color.white);
  setupMenuBar();
  String buttons[] = {"this","is","a","test"};
  buttonBar = new ButtonBar(this,"Button Bar",buttons,ButtonBar.HORIZONTAL);
 }
 void setupMenuBar(){
  Object menuItems[][] = {
   {"File","Exit"},
   {"View","-Button Bar"},
  };
  menuBar = new MyMenuBar(menuItems);
  setMenuBar(menuBar);
 }
 public boolean handleEvent(Event event) {
  if(event.id==Event.WINDOW_DESTROY){
   if(event.target instanceof ButtonBar){
     CheckboxMenuItem buttonItem =
      (CheckboxMenuItem)menuBar.getMenu("View").getItem("Button Bar");
     buttonItem.setState(false);
     return true;
   }
   System.exit(0);
   return true;
  }else if(event.id==Event.ACTION_EVENT){
   if(event.target instanceof MenuItem){
    if("Exit".equals(event.arg)){
     System.exit(0);
     return true;
    }else if("Button Bar".equals(event.arg)){
     CheckboxMenuItem buttonItem =
       (CheckboxMenuItem)menuBar.getMenu("View").getItem("Button Bar");
     boolean viewButtonBar = buttonItem.getState();
     buttonBar.show(viewButtonBar);
     return true;
    }
   }
  }
  return false;
 }
}


When you execute ButtonApp, it displays the opening window shown in Figure 20.9.

Figure 20.9 : The ButtonApp opening window.

Select Button Bar from the View menu, as shown in Figure 20.10.

Figure 20.10 : Selecting Button Bar from the View menu.

The button bar shown in Figure 20.11 is displayed on top of the main ButtonApp window. If you select the View menu once more, you will notice that the Button Bar menu item is implemented as a pull-down menu. It is checked or unchecked depending on whether the button bar is displayed.

Figure 20.11 : The button bar.

The ButtonApp program consists mostly of setup and event-handling software. It declares two field variables, menuBar and buttonBar, that are used to reference the program's menu bar and the button bar. The constructor follows the typical approach to constructing a frame window and creates a 400¥400 window with the ButtonApp title.

The setup() method sets the background to white, creates a menu bar using the MyMenuBar class, and constructs a horizontal button bar using the ButtonBar class constructor introduced in the previous section. The rest of the program consists of event handling.

The WINDOW_DESTROY event is handled a little differently than the typical approach. Remember that this event can be generated for the main application window or for the button bar dialog box. The event.target variable is checked to see if the event was generated for an instance of the ButtonBar class. If so, the checkbox associated with the Button Bar menu is unchecked.

If the WINDOW_DESTROY event was generated for the main application window or the Exit menu item is selected, the program is terminated.

If the Button Bar menu item is selected, the state of the checkbox associated with that menu item is used to determine whether the button bar should be displayed. The show() method inherited from the Component class is used to turn the button bar display on and off.

Using Dialog Boxes

The ButtonBar class illustrates some of the typical methods used with dialog boxes. Most of these methods are not specific to the Dialog class, which provides few methods of its own. Rather, they are inherited from the Window and Component classes, which are superclasses of the Dialog class.

The Dialog class is used to construct a window that is displayed separately from the application menu. The window associated with a Dialog object is not allowed to contain a menu bar. It may be specified as being modal, meaning that it is displayed on top of the main application window until it is hidden or disposed of using the show() and dispose() methods. Most dialog boxes are not as elaborate as that made with the ButtonBar class. They are mainly used to display information to the user and get the user's response via a button click.

The MessageDialog Class

The MessageDialog class provides a custom component that implements the most common types of dialog boxes. It provides a convenient constructor for creating dialog boxes and partially handles the WINDOW_DESTROY event by hiding a dialog box from view. The source code is shown in Listing 20.6.


Listing 20.6. The source code of the MessageDialog class.

package jdg.ch20;

import java.awt.*;

public class MessageDialog extends Dialog {
 public MessageDialog(Frame parent,String title,boolean modal,String text[],
  String buttons[]) {
  super(parent,title,modal);
  int textLines = text.length;
  int numButtons = buttons.length;
  Panel textPanel = new Panel();
  Panel buttonPanel = new Panel();
  textPanel.setLayout(new GridLayout(textLines,1));
  for(int i=0;i<textLines;++i) textPanel.add(new Label(text[i]));
  for(int i=0;i<numButtons;++i) buttonPanel.add(new Button(buttons[i]));
  add("North",textPanel);
  add("South",buttonPanel);
  setBackground(Color.lightGray);
  setForeground(Color.white);
  pack();
  resize(minimumSize());
 }
 public boolean handleEvent(Event event) {
  if(event.id==Event.WINDOW_DESTROY) show(false);
  else if(event.id==Event.ACTION_EVENT && event.target instanceof Button)
   show(false);
  return false;
 }
}


The MessageDialog constructor uses the parent, title, modal, text[], and buttons[] parameters. The parent, title, and modal parameters are passed to the Dialog constructor of its parent class. Two Panel objects are created and assigned to textPanel and buttonPanel. The textPanel layout is specified as a GridLayout object and the buttonPanel layout is the default FlowLayout object. The text[] lines are arranged in a vertical grid in the textPanel. The buttons[] are laid out in a centered horizontal fashion within the buttonPanel. The layout for the MessageDialog object is BorderLayout, by default. The textPanel is added to the top of the dialog box and the buttonPanel is added to the bottom. The foreground and background colors are set to light gray and white. The dialog box is packed and resized to the minimum size needed to contain the two panels.

The MessageApp Program

The MessageApp program shows how the MessageDialog class can be used to implement traditional dialog box functions found in typical window programs. Its source code is shown in Listing 20.7.


Listing 20.7. The source code of the MessageApp program.

import java.awt.*;
import jdg.ch20.MyMenu;
import jdg.ch20.MyMenuBar;
import jdg.ch20.MessageDialog;

public class MessageApp extends Frame {
 MyMenuBar menuBar;
 MessageDialog dialog;
 public static void main(String args[]){
  MessageApp app = new MessageApp();
 }
 public MessageApp() {
  super("MessageApp");
  setup();
  pack();
  resize(400,400);
  show();
 }
 void setup() {
  setBackground(Color.white);
  setupMenuBar();
 }
 void setupMenuBar(){
  Object menuItems[][] = {
   {"File","Exit"},
   {"View","Information","Confirmation","Selection"},
  };
  menuBar = new MyMenuBar(menuItems);
  setMenuBar(menuBar);
 }
 public boolean handleEvent(Event event) {
  if(event.id==Event.WINDOW_DESTROY){
   if(event.target instanceof MessageDialog) return true;
   System.exit(0);
   return true;
  }else if(event.id==Event.ACTION_EVENT){
   if(event.target instanceof MenuItem){
    if("Exit".equals(event.arg)){
     System.exit(0);
     return true;
    }else if("Information".equals(event.arg)){
     String text[] = {"Don't look now, but your shoelace is untied."};
     String buttons[] = {"OK"};
     dialog = new MessageDialog(this,"Information",true,text,buttons);
     dialog.show();
     return true;
    }else if("Confirmation".equals(event.arg)){
     String text[] = {"Do you really want to do this?"};
     String buttons[] = {"Yes","No","Cancel"};
     dialog = new MessageDialog(this,"Confirmation",true,text,buttons);
     dialog.show();
     return true;
    }else if("Selection".equals(event.arg)){
     String text[] = {"What direction do you want to go?",
      "North: cold", "South: warm", "East: humid", "West: arid"};
     String buttons[] = {"North","South","East","West"};
     dialog = new MessageDialog(this,"Selection",true,text,buttons);
     dialog.show();
     return true;
    }
   }
  }
  return false;
 }
}


The MessageApp opening window is shown in Figure 20.12. It supports the File and View pull-down menus.

Figure 20.12 : The MessageApp opening windows.

Select the Information menu item from the View pull-down menu, as shown in Figure 20.13.

Figure 20.13 : Selecting Information from the View menu.

A helpful Information dialog box is displayed, as shown in Figure 20.14. This type of dialog box is typically used to provide information to the user. When the dialog box is displayed, the user acknowledges the information by clicking on the OK button.

Figure 20.14 : The Information dialog box.

Selecting Confirmation from the View menu results in a Confirmation dialog box being displayed to the user, as shown in Figure 20.15. This type of dialog box requests confirmation from the user before attempting to perform an operation that may require the user's approval. If the user clicks the Yes button, the action is performed. If the user clicks No, the operation is not performed. If the user clicks Cancel, an entire series of actions leading up to the confirmation dialog box is aborted.

Figure 20.15 : The Confirmation dialog box.

Choosing the Selection menu item from the View menu results in a multiple-choice Selection dialog box displayed to the user. The user is allowed to pick one from several alternative paths of program execution. (See Figure 20.16.)

Figure 20.16 : The Selection dialog box.

The MessageApp constructor creates a 400¥400 window, titled MessageApp. It uses the MyMenuBar class to construct the program's menu bar. No special processing of note is performed in the application window's construction. The dialog boxes, previously shown, are created by the program's event-handling software.

The handleEvent() method takes the message dialog boxes into account when processing the WINDOW_DESTROY message. It checks to see if the target of the event is a dialog box and, if so, continues with program execution. If the Information menu item is selected, a new MessageDialog object is created with the information shown in Figure 20.14 and the dialog box is displayed to the user using the show() method. The dialog box is modal. The Confirmation and Selection menu items are handled in a similar manner. They create the dialog boxes shown in Figures 20.15 and 20.16 using the MessageDialog() constructor.

The FileDialog Class

The FileDialog class is a custom subclass of the Dialog class. The FileDialog class uses the operating system's native dialog boxes to query the user for the name of a file to be loaded or saved. The getDirectory() and getFile() methods return the file's directory and filename. The setDirectory() and setFile() methods are used to set the state of the dialog box to a particular directory and file when it is initially opened. The getMode() method returns the LOAD or SAVE mode of the dialog box. The setFileNameFilter() and getFileNameFilter() methods are used to associate an object of the FileNameFilter interface with the dialog box. No classes that implement this interface are currently provided by the Java API. The TextEdit example in Chapter 18 illustrates the use of the FileDialog class in performing file load and save operations.

Summary

This chapter shows you how to use the Menu, Button, and Dialog classes. It describes the available menu and button options and shows you how to quickly and easily construct menus and buttons for your window programs using the MyMenu, MyMenuBar, and ButtonBar classes. The use of dialog boxes is also covered. You have created the MessageDialog class, which you can reuse in other programs. Chapter 21, "Checkboxes, Choices, and Lists," shows you how to work with those elements.