Computing Concepts with Java 2 Essentials
Laboratory Notebook
Chapter 12 - Graphical User Interfaces


Your name:
Your email address:
Your student ID number:

Once this form has been customized for your institution, you can use this button to send your lab work. Be sure to read the instructions before starting your work.


Lab Objectives

To gain experience with


All problems in this lab are based on the HelloTest program that is similar to the program developed in Lab 10.

P1. Buttons

In this problem, we want to add two buttons to the bottom of the frame, like this:

{short description of image}

Follow these steps:

  1. Make two instance variables of the class JButton:
    private JButton smallerButton;
    private JButton largerButton;
    
  2. In the frame constructor, initialize the variables with JButton objects:
    smallerButton = new JButton("Smaller");
    largerButton = new JButton("Larger");
    
  3. Place the buttons into a panel:
    JPanel southPanel = new JPanel();
    southPanel.add(smallerButton);
    southPanel.add(largerButton);
    
  4. Add that panel to the "South" end of the content pane:
    contentPane.add(southPanel, "South");

Make these changes in your program. Run the program to see that the buttons appear. Of course, clicking the buttons won't yet have any effect.

Next, we want to hook up the buttons to actions. For each button, you need to carry out these steps:

  1. Create a class that implements the ActionListener interface and override the actionPerformed method.
  2. Make an object of that class
  3. Install that object as the action listener of the button

Let's carry out these steps one by one.

When the "Larger" button is clicked, we want to increase the font size by 25%. When the "Smaller" button is clicked, we want to decrease it again. To avoid integer rounding errors, we keep a floating-point variable fontSizeFactor that is initialized with 1. Clicking on the buttons multiplies by 1.25 or 0.8 (because 0.8 = 1 / 1.25).

Here is an appropriate action listener for the "Larger" button.

class LargerFontAction implements ActionListener
{  public void actionPerformed(ActionEvent event)
   {  fontSizeFactor = 1.25 * fontSizeFactor;
      panel.setMessageSize((int)(fontSizeFactor * DEFAULT_SIZE));
   }
}

This class is an inner class of the frame class since the actionPerformed method needs to access the panel and fontSizeFactor instance variables of the frame class.

To hook it up to the "Larger" button, you need to create an object of this class and set it as an action listener of the button. Place the following instructions into the frame constructor:

LargerFontAction largerAction = new LargerFontAction();
largerButton.addActionListener(largerAction);

Try it out--add the code, compile the program and click on the "Larger" button. The font should be increased every time you click the button. Clicking on the "Smaller" button does not yet have any effect.

Now do the same for the "Smaller" button. Make an action listener class, and add an instance of that class as an action listener of the smallerButton. Run your program. Both buttons should now work.

In this program, the two button actions are very closely related. Both multiply the fontSizeFactor with a number. You can reduce the number of classes by recognizing that commonality. Let's make the scale factor (1.25 or 0.8) an instance variable of the action listener class.

class FontAction implements ActionListener
{  public FontAction(double f)
   {  scaleFactor = f;
   }

   public void actionPerformed(ActionEvent event)
   {  fontSizeFactor = scaleFactor * fontSizeFactor;
      panel.setMessageSize((int)(fontSizeFactor * DEFAULT_SIZE));
   }

   private double scaleFactor;
}

Then you can simply add a new ButtonListener(1.25) as the action listener of the largerButton, and a new ButtonListener(0.8) as the action listener of the smallerButton.

Try out this enhancement. Remove the LargerFontAction and SmallerFontAction classes and replace them with the FontAction class.


P2. Menus

In this program, we will use a menu instead of a set of buttons to increase and decrease the font size.

{short description of image}

As with buttons, you need to solve two unrelated issues:

In Java, there is a three-level hierarchy for menus.

  1. A menu bar is attached to a window
  2. The menu bar contains menus, rectangular panels with menu strings inside them.
  3. Menus contain submenus and menu items.

Only menu items have actions associated with them.

Here are the instructions to build the menu for this program.

JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);

JMenu fontMenu = new JMenu("Font");
menuBar.add(fontMenu);

JMenuItem largerItem = new JMenuItem("Larger");
fontMenu.add(largerItem);

JMenuItem smallerItem = new JMenuItem("Smaller");
fontMenu.add(smallerItem);

Place these instructions into the constructor of the frame class of the HelloTest program.

Run your program and check that the menu works. Of course, selecting the menu items does not yet have any effect.

Next, you need to attach actions to the menu items. This process is identical to attaching actions to buttons.

In particular, you can simply reuse the FontAction class from the preceding exercise.

FontAction largerAction = new FontAction(1.25);
largerItem.addActionListener(largerAction);

Attach these actions to the two menu items and run your program. Check that selecting the menu items increases and decreases the font size.


P3. Combo Boxes

In this exercise, you will see how to offer a user a selection among multiple choices. You can place all choices into a combo box.

{short description of image}

To build such a combo box, you add items into it:

comboBox = new JComboBox();
comboBox.addItem("Small");
comboBox.addItem("Medium");
comboBox.addItem("Large");
comboBox.addItem("Extra Large");

Then place the combo box in the south end of the content pane. You still want to enclose the combo box inside a panel, even though it is a single item.

JPanel southPanel = new JPanel();
southPanel.add(comboBox);
contentPane.add(southPanel, "South");

If you added the combo box directly to the content pane, then it would grow to a monstrous size and fill the entire "South" region. The panel keeps it small and centered.

Try it out. Add the combo box to the frame of the HelloTest program. Compile and run the program. Pull down the item list of the combo box to see the items. Of course, selecting the items does not yet have an effect.

To activate the combo box, you need to attach an action listener. The actionPerformed method needs to find which item the user selected.

class ComboAction implements ActionListener
{  public void actionPerformed(ActionEvent event)
   {  String item = (String)comboBox.getSelectedItem();
      . . .
   }
}

You need to cast the return value of the getSelectedItem method to a String because it is possible to put other objects (such as icons) into a combo box.

Now you simply set the correct font size, depending on the item string.

int messageSize = DEFAULT_SIZE;
if (item.equals("Small")) { messageSize = SMALL_SIZE; }
else if (item.equals("Medium")) { messageSize = MEDIUM_SIZE; }
else if (item.equals("Large")) { messageSize = LARGE_SIZE; }
else if (item.equals("Extra Large")) { messageSize = EXTRA_LARGE_SIZE; }
panel.setMessageSize(messageSize);

Define the size constants as follows:

public static final int SMALL_SIZE = 12;
public static final int MEDIUM_SIZE = 18;
public static final int LARGE_SIZE = 24;
public static final int EXTRA_LARGE_SIZE = 36;

Next, you need to create an object of this class and make it the action listener of the combo box:

ComboAction action = new ComboAction();
comboBox.addActionListener(action);

Add the combo action listener and try out your program. When you select an item from the combo box, the message should be displayed in the appropriate size.


P4. Radio buttons and check boxes

Radio buttons offer another way for offering the user a selection among multiple alternatives.

{short description of image}

These buttons are called radio buttons because they work like the channel buttons on a radio. If you select one of them, the previously selected one is turned off.

However, radio buttons take up more screen "real estate" than combo boxes and therefore are best if you only need to offer users a small selection.

Here are the instructions to construct two radio buttons:

helloButton = new JRadioButton("Hello");
goodbyeButton = new JRadioButton("Goodbye");

To get the "radio button" effect, where all other buttons are turned off when one of the buttons is clicked, you need to place the buttons in a button group:

ButtonGroup group = new ButtonGroup();
group.add(helloButton);
group.add(goodbyeButton);

Finally, you want to turn the first button on:

helloButton.setSelected(true);

The button group is a logical grouping of the buttons. You still need to physically lay out the buttons on the screen:

JPanel southPanel = new JPanel();
southPanel.add(helloButton);
southPanel.add(goodbyeButton);
contentPane.add(southPanel, "South");

Add the two radio buttons to the frame of the HelloTest program. Run the program. Observe how clicking on one button turns off the other button. Of course, clicking the buttons has no further effect because we have not yet attached any action.

We want to change the message text when the user clicks on a radio button. To assemble the correct text, we simply check which button is currently selected.

class MessageAction implements ActionListener
{  public void actionPerformed(ActionEvent event)
   {  String message = "";
      if (helloButton.isSelected()) message = "Hello";
      else if (goodbyeButton.isSelected()) message = "Goodbye";
      message += ", World!";
      panel.setMessageText(message);
   }
}

We can attach the same action object to both buttons:

MessageAction action = new MessageAction();
helloButton.addActionListener(action);
goodbyeButton.addActionListener(action);

Add the action listener and attach it to the radio buttons. Run the program. Observe how clicking on the buttons changes the message text.

Check boxes are used to let users select a single logical alternative, typically of the form "do X" or "do nothing". Here, we use a check box to let the user specifiy whether the word "cruel" should be added to the message text:

{short description of image}

Follow these steps to add the check box to the program:

  1. Construct the check box.
    cruelCheckBox = new JCheckBox("Cruel");
  2. Attach the same action listener to the check box and the radio buttons.
    cruelCheckBox.addActionListener(action);
  3. Add the check box to the south panel.
    southPanel.add(cruelCheckBox);
  4. In the actionPerformed method of the MessageAction class, check
    if (cruelCheckBox.isSelected()) . . .

Run the program. Observe how clicking on the check box changes the message text.


Don't forget to send your answers when you're finished.