Skip to main content

Section 8.4 Example: A Toggle Button

The ability to extend an existing class is one of the most powerful features of object-oriented programming. It allows objects to reuse code defined in the superclasses without having to redefine or recompile the code.

In this section, we will use inheritance to design a ToggleButton as a JButton subclass. As its name suggests, it will toggle its label whenever it is clicked, in addition to carrying out some kind of associated action. It will behave like a light switch, toggling between “on” and “off” as it turns the lights on or off.

Subsection 8.4.1 The ToggleButton class

By default, a JButton has just a single label. The main idea in our design is that a ToggleButton is a JButton that has two labels, as in Figure 8.4.1.

Figure 8.4.1. ToggleButton class

Note that we give it a constructor method that will allow us to provide the initial values of its labels. Another important feature is that it implements the ActionListener interface, which will enable it to toggle its label whenever it is clicked.

Subsection 8.4.2 Implementation Details

The complete definition of ToggleButton is given in Listing 8.4.2.

Note how we have defined its constructor. Recall that a subclass constructor must call its superclass constructor. In this case we call super(l1), setting the JButton label through the first of the two ToggleButton labels. This initializes the button's label. This will be the label that appears on the button when it is first displayed.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ToggleButton extends JButton
                        implements ActionListener {
  private String label1;   // Toggle between two labels
  private String label2;
  public ToggleButton(String l1, String l2) {// Constructor
    super(l1);          // Use l1 as the default label
    label1 = l1;
    label2 = l2;
    addActionListener(this);
  }
  public void actionPerformed(ActionEvent e) {
    String tempS = label1;  // Swap the labels
    label1 = label2;
    label2 = tempS;
    setText(label1);
  } // actionPerformed()
} // ToggleButton
Listing 8.4.2. Definition of the ToggleButton class.

Notice also in the constructor that the ToggleButton adds itself as its own ActionListener, so whenever it is clicked, its actionPerformed() method will be invoked.

The actionPerformed() method toggles between label1 and label2 and uses the inherited setText() method to set the buttons label to label1.

Subsection 8.4.3 Swapping Algorithm

Swapping two values in memory is a standard programming practice used in lots of different algorithms. It requires a temporary variable, as described in the following algorithm.

Consider the following trace of the algorithm, where var1 and var2 are integers:

temp  var1  var2    code
----  ----  ----    ----
 -    5     7       0. initial values
 5    5     7       1. temp = var1
 5    7     7       2. var1 = var2
 5    7     5       3. var2 = temp
 -    7     5       4. swapped values

As you can see, the purpose of temp is to save the value of var1, which is overwritten by var2 in the second step of the algorithm.

Exercises Self-Study Exercises

1. Swap Error.

The following program has an error in it. It's supposed to swap var1 in var2. First run it to see the error. Then fix the error and run it again.

public class Swap {
  public static void main(String args[]) {
    String var1 = "on", var2 = "off";
    System.out.println("var1=" + var1 + " var2=" + var2);
    var1 = var2;
    var2 = var1;
    System.out.println("var1=" + var1 + " var2=" + var2);
  }
}

Subsection 8.4.4 The LightSwitch app

Now that we have seen that a ToggleButton toggles its label between two values, what about performing an associated action? To do this, we will need multiple event handlers, one to handle the toggling of the button's label and the other to handle its associated action (Fig 8.4.5).

Figure 8.4.5. NEEDS TO BE UPDATED. The ToggleButton has two ActionListeners, each of which will take its own independent action.

In this design, one listener is associated with the ToggleButton itself and the other with the object that uses the ToggleButton.

The implementation of this design is given by LightSwitchTester (Listing 8.4.6). LightSwitchTester extends JFrame and implements the ActionListener interface. The ToggleButton (named lightSwitch) simulate a light switch. Whenever it is pressed, the LightSwitchTester will report whether the light is on or off and the lightSwitch will toggle its label.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class LightSwitchTester extends JFrame
                            implements ActionListener {

  private ToggleButton lightSwitch;
  
  public LightSwitchTester() {
    lightSwitch = new ToggleButton ("off","on");
    getContentPane().add(lightSwitch);
    LightSwitchTester.addActionListener(this);
  } // constructor()

  public void actionPerformed(ActionEvent e)  {
    setTitle("The light is " + lightSwitch.getText());
  } // actionPerformed()

   public static void main(String args[]) {
      JFrame f = new LightSwitchTester();
      f.setSize(200,200);
      f.setVisible(true);
   }
} // LightSwitchTester
Listing 8.4.6. Definition of the LightSwitch class.

When lightSwitch is clicked, the program displays the message, “The light is on,” or “The light is off,” in the program's title bar (Figure 8.4.7). This is a somewhat trivial action but it illustrates that a ToggleButton both toggles its own label and carries out some associated action.

Figure 8.4.7. NEEDS TO BE UPDATED. When clicked, LightSwitch button causes “The light is on” or “The light is off” to appear in the window's title bar.

The ToggleButton design satisfies several key design principles of object-oriented programming. First and foremost, it uses inheritance to extend the functionality of the predefined JButton class—the extensibility principle. Secondly, it encapsulates a ToggleButton's essential behavior within the ToggleButton class itself—the modularity principle. Finally, it hides the mechanism by which a ToggleButton manages its labels—the information-hiding principle.

Exercises Self-Study Exercises

  1. Suppose you are designing an GUI that plays a card game, and you want a single button that can be used both to deal the cards and to collect the cards. Write a code segment that creates this type of button, adds it to the JFrame, and designates the JFrame as its ActionListener.

You have attempted of activities on this page.