Events, Event Sources, and Event Listeners

 

In the applications that you have written so far, user input was under control of the program. The program asked the user for input in a specific order. For example, a program might ask the user to supply first a name, then a dollar amount. But the programs that you use every day on your computer don't work like that. In a program with a modern graphical user interface, the user is in control. The user can use both the mouse and the keyboard and can manipulate many parts of the user interface in any desired order. For example, the user can enter information into text fields, pull down menus, click buttons, and drag scroll bars in any order. The program must react to the user commands, in whatever order they arrive. Having to deal with many possible inputs in random order is quite a bit harder than simply forcing the user to supply input in a fixed order.

 

In the following sections, you will learn how to write Java programs that can react to user interface events, such as button pushes and mouse clicks. The Java windowing toolkit has a very sophisticated mechanism that allows a program to specify the events in which it is interested and which objects to notify when one of these events occurs.

 

 

User interface events include key presses, mouse moves, button clicks, menu selections, and so on.

 

 

 

 

Whenever the user of a graphical program types characters or uses the mouse anywhere inside one of the windows of the program, the Java window manager sends a notification to the program that an event has occurred. The window manager generates huge numbers of events. For example, whenever the mouse moves a tiny interval over a window, a “mouse move” event is generated. Events are also generated when the user presses a key, clicks a button, or selects a menu item.

 

Most programs don't want to be flooded by boring events. For example, when a button is clicked with the mouse, the mouse moves over the button, then the mouse button is pressed, and finally the button is released. Rather than receiving lots of irrelevant mouse events, a program can indicate that it only cares about button clicks, not about the underlying mouse events. However, if the mouse input is used for drawing shapes on a virtual canvas, it is necessary to closely track mouse events.

 

 

An event listener belongs to a class that is provided by the application programmer. Its methods describe the actions to be taken when an event occurs.

 

 

 

 

Every program must indicate which events it needs to receive. It does that by installing event listener objects. An event listener object belongs to a class that you define. The methods of your event listener classes contain the instructions that you want to have executed when the events occur.

 

To install a listener, you need to know the event source . The event source is the user interface component that generates a particular event. You add an event listener object to the appropriate event sources. Whenever the event occurs, the event source calls the appropriate methods of all attached event listeners.

 

 

Event sources report on events. When an event occurs, the event source notifies all event listeners.

 

 

 

Use JButton components for buttons. Attach an ActionListener to each button.

 

 

 

 

This sounds somewhat abstract, so let's run through an extremely simple program that prints a message whenever a button is clicked. Button listeners must belong to a class that implements the ActionListener interface:

public interface ActionListener
{
   void actionPerformed(ActionEvent event);
}

This particular interface has a single method, actionPerformed. It is your job to supply a class whose actionPerformed method contains the instructions that you want executed whenever the button is clicked. Here is a very simple example of such a listener class:

ch09/button1/ClickListener.java
 
1  import java.awt.event.ActionEvent;
2  import java.awt.event.ActionListener;
3
4  /**
5     An action listener that prints a message.
6  */
7  public class ClickListener implements ActionListener
8  {
9     public void actionPerformed(ActionEvent event)
10    {
11       System.out.println(“I was clicked.”);
12    }
13 }

 

We ignore the event parameter of the actionPerformed method—it contains additional details about the event, such as the time at which it occurred.

 

Once the listener class has been defined, we need to construct an object of the class and add it to the button:

 

ActionListener listener = new ClickListener();
button.addActionListener(listener);

Whenever the button is clicked, it calls

listener.actionPerformed(event);

As a result, the message is printed.

 

You can think of the actionPerformed method as another example of a callback, similar to the measure method of the Measurer class. The windowing toolkit calls the actionPerformed method whenever the button is pressed, whereas the DataSet calls the measure method whenever it needs to measure an object.

 

You can test this program out by opening a console window, starting the ButtonViewer program from that console window, clicking the button, and watching the messages in the console window (see Figure bellow).

 

ch09/button1/ButtonViewer.java
 
1  import java.awt.event.ActionListener;
2  import javax.swing.JButton;
3  import javax.swing.JFrame;
4
5  /**
6     This program demonstrates how to install an action listener.
7  */
8  public class ButtonViewer
9  {
10    public static void main(String[] args)
11    {
12       JFrame frame = new JFrame();
13       JButton button = new JButton(”Click me!”);
14       frame.add(button);
15
16       ActionListener listener = new ClickListener();
17       button.addActionListener(listener);
18
19       frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
20       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
21       frame.setVisible(true);
22    }
23
24    private static final int FRAME_WIDTH = 100;
25    private static final int FRAME_HEIGHT = 60;
26 }
 
 
 

FIGURE 

Implementing an Action Listener

 
 
      _____________________________________________________________________________________________________________
 
         Applet 
 
import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
 
/**
   This applet lets the user move a rectangle by specifying
   the x- and y-position of the top left corner.
*/
public class ButtonApplet extends Applet
{  
   public ButtonApplet()
   {  
      // the rectangle that the paint method draws
      box = new Rectangle(BOX_X, BOX_Y, 
         BOX_WIDTH, BOX_HEIGHT);
 
      // the text fields for entering the x- and y-coordinates
      final JTextField xField = new JTextField(5);
      final JTextField yField = new JTextField(5);
 
      // the button to move the rectangle
      JButton moveButton = new JButton("Move",
          new ImageIcon("hand.gif"));     
 
      class MoveButtonListener implements ActionListener
      {
         public void actionPerformed(ActionEvent event)
         {
            int x = Integer.parseInt(xField.getText());
            int y = Integer.parseInt(yField.getText());
            box.setLocation(x, y);
            repaint();
         }
      }
 
      ActionListener listener = new MoveButtonListener();
      moveButton.addActionListener(listener);
 
      // the labels for labeling the text fields
      JLabel xLabel = new JLabel("x = ");
      JLabel yLabel = new JLabel("y = ");
 
      // the panel for holding the user interface components
      JPanel panel = new JPanel();
 
      panel.add(xLabel);
      panel.add(xField);
      panel.add(yLabel);
      panel.add(yField);
      panel.add(moveButton);
 
      // the frame for holding the component panel
      JFrame frame = new JFrame();
      frame.setContentPane(panel);
      frame.pack();
      frame.show();
   }
 
   public void paint(Graphics g)
   {  
      Graphics2D g2 = (Graphics2D)g;
      g2.draw(box);
   }
 
   private Rectangle box;
   private static final int BOX_X = 100;
   private static final int BOX_Y = 100;
   private static final int BOX_WIDTH = 20;
   private static final int BOX_HEIGHT = 30;
}