Programming with the Java Event Model

   

Java™ 2 Primer Plus
By Steven Haines, Steve Potts

Table of Contents
Chapter 14.  Event Delegation Model


GUIs are event-generating machines. Every movement of the mouse, every keystroke, every window resizing, and every window relocation generates events that your application might be interested in knowing about. Directing your attention to the word "might" in the preceding sentence will focus your attention on the crux of the event-handling challenge.

Any single Java application or JavaBean is only going to be interested in a small subset of the events that are picked up by the JVM. If your application were notified of every event that the JVM receives, it would be overwhelmed by the overhead involved in processing them all.

Starting with Java 1.1, Sun introduced an improved event-handling strategy based on the concept of event listeners. An event listener is a class that implements the java.awt.event.EventListener interface, normally through one of EventListener subinterfaces. A few of these subinterfaces are listed here:

 ActionListener, AdjustmentListener, ChangeListener, ComponentListener,  ConnectionEventListener, ContainerListener, ControllerEventListener, FocusListener,  ItemListener, KeyListener, LineListener, ListDataListener, ListSelectionListener,  MenuListener, MouseInputListener, MouseListener, MouseMotionListener,  MouseWheelListener, WindowStateListener 

Each of these interfaces requires that one or more methods be written by any class that implements it. For example, the MouseListener interface requires that all five of the following methods be implemented:

 mouseClicked(MouseEvent e)  mouseEntered(MouseEvent e)  mouseExited(MouseEvent e)  mousePressed(MouseEvent e)  mouseReleased(MouseEvent e) 

By contrast, the ActionListener interface only requires one method:

 actionPerformed(ActionEvent e) 

Notice that each method is handed some sort of an object with Event in its name. All these methods receive an object that is derived from java.awt.Event. Each of these derived classes contains methods specific to its needs that enable the listener to obtain more information about the nature of the event. For example, an ActionEvent class contains four methods:

  • getActionCommand() returns the command string associated with this action.

  • getModifiers() returns the modifier keys held down during this action event.

  • getWhen() returns the timestamp of when this event occurred.

  • paramString() returns a parameter string for this action event.

Most of the time the JVM creates the Event object from the hardware event that is received. It interprets this hardware event and translates it into an object that the Java programmer will be able to handle easily.

Listing 14.1 will show how this all works:

Listing 14.1 The EventCreator.java File
 /*   * EventCreator.java   *   * Created on August 8, 2002, 12:42 PM   */  package ch14;  import javax.swing.*;  import java.awt.event.ActionListener;  import javax.swing.border.EtchedBorder;  import java.awt.Container;  import java.awt.BorderLayout;  import java.util.*;  /**   *   * @author  Stephen Potts   * @version   */  public class EventCreator extends JFrame  {      JButton btnBook;      JButton btnExit;      /** Constructors for CruiseList */      public EventCreator() throws Exception      {          try          {              //configure the Frame              EventConsumer ec = new EventConsumer();              setBounds(150,200,500,250);              setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);              //set the layout              BorderLayout border = new BorderLayout();              Container content = getContentPane();              content.setLayout(border);              btnBook = new JButton("Book");               btnExit = new JButton("Exit");              btnBook.addActionListener(ec);              btnExit.addActionListener(ec);              JPanel bottomPanel = new JPanel();              bottomPanel.add(btnBook);              bottomPanel.add(btnExit);              content.add(bottomPanel, BorderLayout.SOUTH);              setVisible(true);          }catch(Exception e)          {              System.out.println("Exception thrown " + e);          }      }      /**       * @param args the command line arguments       */      public static void main(String args[])      {          //create an instance of the GUI          try          {              EventCreator mainWindow = new EventCreator();          }catch(Exception e)          {              System.out.println("Exception in main " + e);          }      }  }//class 

The GUI objects that generated these events are two JButtons.

 JButton btnBook;   JButton btnExit; 

We create an instance of the event listener class here.

 EventConsumer ec = new EventConsumer(); 

Next, we instantiate the buttons and call the addActionListener() method on each button so that there will be a class to handle any Action events that these buttons generate.

 btnBook = new JButton("Book");  btnExit = new JButton("Exit");  btnBook.addActionListener(ec);  btnExit.addActionListener(ec); 

For this class to compile, we have to have a class called EventConsumer.java to handle the events.

Listing 14.2 shows this class:

Listing 14.2 The EventConsumer.java File
 /*   * EventConsumer.java   *   * Created on January 24, 2002, 11:31 AM   */  package ch14;  import javax.swing.*;  import java.awt.event.ActionListener;  import javax.swing.border.EtchedBorder;  import java.awt.Container;  import java.awt.BorderLayout;  import java.util.*;  /**   *   * @author  Stephen Potts   * @version   */  public class EventConsumer implements ActionListener  {      JButton btnBook;       JButton btnExit;      /** Constructors for CruiseList */      public EventConsumer() throws Exception      {      }      public void actionPerformed(java.awt.event.ActionEvent ae)      {          if (ae.getActionCommand().equals("Exit"))          {              System.out.println("Exit was clicked");          }          //Try and book a ticket          if (ae.getActionCommand().equals("Book"))          {              System.out.println("Book was clicked");          }      }  }//class 

Several lines of code in these two listings require explanation:

  • Notice that this application contains two classes instead of one. This application could have been written with the EventCreator class serving as its own event listener. It was written as two classes for clarity.

  • Both buttons are of class JButton. JButton is derived from the class javax.swing.AbstractButton. One of AbstractButton's methods is addActionListener(). AbstractButton extends JComponent. JComponent is an abstract class that contains a list of all the listeners of every type. Whenever an event occurs in a program, this list is searched to find the listeners to notify.

  • Whenever the buttons are clicked, the JButton code creates an ActionEvent object. It then looks at the listener list to find out who the listeners are for this component. Of those listeners on the list, the JButton chooses the ones that implement the ActionListener interface. It then makes a call to each one of these listeners' actionPerformed() method. The code in the actionPerformed() method is executed.

  • There is only one actionPerformed() method for all components that can create action events in this application. This means that the actionPerformed() method must use the getActionCommand() method of the ActionEvent class to figure out which button was clicked. The getActionCommand() returns the label of the component that caused the Event object to be created.

The result from running this code is shown in Figure 14.2:

Figure 14.2. The EventCreator application uses a dialog to communicate the event to the EventConsumer event handler.

graphics/14fig02.gif

Running this program generates the following output in a console window:

 Book was clicked  Exit was clicked  Book was clicked  Exit was clicked 

This example showed the basic procedure that must be followed to connect the events that one component is able to generate, with the event handling code that has been written specifically for it. Many different event types and many different methods for handling each of them exist. In the end, however, they all follow the same pattern of a listener registering with an event creator.

An alternate way of listening for events is to make the single class its own event listener. All that you have to do to accomplish this is to make that class implement the listener interface itself and change the addActionListener() calls to pass the parameter this, indicating that this class handles its own events. Listing 14.3 shows an example of how this works.

Listing 14.3 The EventCreator2.java Class
 /*   * EventCreator2.java   *   * Created on August 8, 2002, 12:42 PM   */  package ch14;  import javax.swing.*;  import java.awt.event.ActionListener;  import javax.swing.border.EtchedBorder;  import java.awt.Container;  import java.awt.BorderLayout;  import java.util.*;  /**   *   * @author  Stephen Potts   * @version   */  public class EventCreator2 extends JFrame implements ActionListener  {      JButton btnBook;      JButton btnExit;      /** Constructors for CruiseList */      public EventCreator2() throws Exception      {          try          {              //configure the Frame              System.out.println("EventCreator2 executing");              setBounds(150,200,500,250);              setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);              //set the layout              BorderLayout border = new BorderLayout();              Container content = getContentPane();              content.setLayout(border);              btnBook = new JButton("Book");              btnExit = new JButton("Exit");              btnBook.addActionListener(this);              btnExit.addActionListener(this);              JPanel bottomPanel = new JPanel();              bottomPanel.add(btnBook);              bottomPanel.add(btnExit);              content.add(bottomPanel, BorderLayout.SOUTH);              setVisible(true);          }catch(Exception e)          {               System.out.println("Exception thrown " + e);          }      }      public void actionPerformed(java.awt.event.ActionEvent ae)      {          if (ae.getActionCommand().equals("Exit"))          {              System.out.println("Exit was clicked2");          }          //Try and book a ticket          if (ae.getActionCommand().equals("Book"))          {              System.out.println("Book was clicked2");          }      }      /**       * @param args the command line arguments       */      public static void main(String args[])      {          //create an instance of the GUI          try          {              EventCreator2 mainWindow = new EventCreator2();          }catch(Exception e)          {              System.out.println("Exception in main " + e);          }      }  }//class 

Now both the generation of events and their handling is done in the same class. The declaration of the class itself has to change to implement the additional interface.

 public class EventCreator2 extends JFrame implements ActionListener 

Instead of using a different class as the ActionListener, we now use this class.

 btnBook.addActionListener(this);  btnExit.addActionListener(this); 

The actionPerformed() method is now found in this class.

 public void actionPerformed(java.awt.event.ActionEvent ae)  {      if (ae.getActionCommand().equals("Exit"))      {          System.out.println("Exit was clicked2");      }      //Try and book a ticket      if (ae.getActionCommand().equals("Book"))      {          System.out.println("Book was clicked2");      }  } 

Notice that it is identical to when it was in a separate class.

The GUI for this class is identical to the one shown in Figure 14.2, but the output to the screen has changed:

 EventCreator2 executing  Book was clicked2  Exit was clicked2  Book was clicked2  Exit was clicked2 

This change was intentionally done so that we could distinguish between this example's output and the example in Listing 14.2. Functionally, both of these examples are equivalent.

It is more common to have the class serve as its own listener, but both approaches are considered good form. Now that we understand something about event listeners in general, we need to look at some more of the event listener classes.


       
    Top
     



    Java 2 Primer Plus
    Java 2 Primer Plus
    ISBN: 0672324156
    EAN: 2147483647
    Year: 2001
    Pages: 332

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net