Java Cookbook, Second Edition

Problem

Your button doesn't do anything when the user presses it.

Solution

Add an ActionListener to do the work.

Discussion

Event listeners come in about half a dozen different types. The most common is the ActionListener, used by push buttons, text fields, and certain other components to indicate that the user has performed a high-level action, such as activating a push button or pressing Enter in a text field. The paradigm (shown in Figure 14-3) is that you create a Listener object, register it with the event source (such as the push button), and wait. Later, when and if the user pushes the button, the button will call your Listener.

Figure 14-3. AWT listener relationships

Here's some simple code in which pushing a button causes the program to print a friendly message. This program is an applet (see Recipe Recipe 18.2), so it can use the showStatus( ) method to print its text:

import java.applet.*; import java.awt.*; import java.awt.event.*; /** Demonstrate use of Button */ public class ButtonDemo extends Applet implements ActionListener { Button b1; public ButtonDemo( ) { add(b1 = new Button("A button")); b1.addActionListener(this); } public void actionPerformed(ActionEvent event) { showStatus("Thanks for pushing my button!"); } }

This version does not use an inner class to handle the events but does so itself by directly implementing the ActionListener interface. This works for small programs, but as an application grows, it quickly becomes unserviceable; how do you sort out which button was pressed? To solve this problem, we normally use an inner class as the action handler and have a different class for each button. First, let's write the previous code with two buttons so that you can see what I mean:

import java.applet.*; import java.awt.*; import java.awt.event.*; /** Demonstrate use of two buttons, using a single ActionListener, * being the class itself. */ public class ButtonDemo2a extends Applet implements ActionListener { Button b1, b2; public void init( ) { add(b1 = new Button("A button")); b1.addActionListener(this); add(b2 = new Button("Another button")); b2.addActionListener(this); } public void actionPerformed(ActionEvent e) { if (e.getSource( ) == b1) showStatus("Thanks for pushing my first button!"); else showStatus("Thanks for pushing my second button!"); } }

Now here it is using a member inner class , that is, a class that is a named part of another class:

import java.applet.*; import java.awt.*; import java.awt.event.*; /** Demonstrate use of two buttons, using a single ActionListener * made of a named inner class */ public class ButtonDemo2b extends Applet { Button b1, b2; ActionListener handler = new ButtonHandler( ); public void init( ) { add(b1 = new Button("A button")); b1.addActionListener(handler); add(b2 = new Button("Another button")); b2.addActionListener(handler); } class ButtonHandler implements ActionListener { public void actionPerformed(ActionEvent e) { if (e.getSource( ) == b1) showStatus("Thanks for pushing my first button!"); else showStatus("Thanks for pushing my second button!"); } } }

Note that merely breaking the action handling code into its own class doesn't really contribute much to readability. But there is a way to use inner classes that does promote readability and maintainability. We create an inner class (see Recipe 9.6) for each event source each button, each menu item, and so on. Sounds like a lot of work, and it would be, if you used the previous method. But there is a shorter way, using anonymous inner classes, described next.

Категории