15.8. Combo Boxes

 
[Page 465 ( continued )]

14.3. Listeners, Registrations, and Handling Events

Java uses a delegation -based model for event handling: a source object fires an event, and an object interested in the event handles the event. The latter object is called a listener . Two things are needed for an object to be a listener for an event on a source object, as shown in Figure 14.3.


[Page 466]
Figure 14.3. A listener must be an instance of a listener interface and must be registered with a source component.


  1. [Page 467]
  2. The listener object must be an instance of the corresponding event-listener interface to ensure that the listener has the correct method for processing the event. Java provides a listener interface for every type of GUI event. The listener interface is usually named XListener for XEvent , with the exception of MouseMotionListener . For example, the corresponding listener interface for ActionEvent is ActionListener ; each listener for ActionEvent should implement the ActionListener interface. Table 14.2 lists event types, the corresponding listener interfaces, and the methods defined in the listener interfaces. The listener interface contains the method(s), known as the handler(s) , invoked by the source object to process the event.

    Table 14.2. Events, Event Listeners, and Listener Methods
    Event Class (Handlers) Listener Interface Listener Methods
    ActionEvent ActionListener actionPerformed(ActionEvent)
    ItemEvent ItemListener itemStateChanged(ItemEvent)
    MouseEvent MouseListener mousePressed(MouseEvent)
        mouseReleased(MouseEvent)
        mouseEntered(MouseEvent)
        mouseExited(MouseEvent)
        mouseClicked(MouseEvent)
      MouseMotionListener mouseDragged(MouseEvent)
        mouseMoved(MouseEvent)
    KeyEvent KeyListener keyPressed(KeyEvent)
        keyReleased(KeyEvent)
        keyTyped(KeyEvent)
    WindowEvent WindowListener windowClosing(WindowEvent)
        windowOpened(WindowEvent)
        windowIconified(WindowEvent)
        windowDeiconified(WindowEvent)
        windowClosed(WindowEvent)
        windowActivated(WindowEvent)
        windowDeactivated(WindowEvent)
    ContainerEvent ContainerListener componentAdded(ContainerEvent)
        componentRemoved(ContainerEvent)
    ComponentEvent ComponentListener componentMoved(ComponentEvent)
        componentHidden(ComponentEvent)
        componentResized(ComponentEvent)
        componentShown(ComponentEvent)
    FocusEvent FocusListener focusGained(FocusEvent)
        focusLost(FocusEvent)
    AdjustmentEvent AdjustmentListener adjustmentValueChanged (AdjustmentEvent)


    [Page 468]
  3. The listener object must be registered by the source object. Registration methods are dependent on the event type. For ActionEvent , the method is addActionListener . In general, the method is named addXListener for XEvent . A source object may fire several types of events. For each event, the source object maintains a list of listeners and notifies all the registered listeners by invoking the handler on the listener object to respond to the event, as shown in Figure 14.4. (Figure 14.4 shows the internal implementation of a source class. It addresses the question how a handler is invoked.)

    Figure 14.4. The source object notifies the listeners of the event by invoking the handler of the listener object.

Now you have the answers to all your questions about the simple example in Listing 14.1. Since a JButton object fires ActionEvent , a listener object for ActionEvent must be an instance of ActionListener , so the listener class implements ActionListener in line 26. The source object invokes addActionListener(listener) to register a listner , as follows :

 JButton jbt =   new   JButton(   "OK"   );  // Line 7 in Listing 14.1  ActionListener listener =   new   OKListener();  // Line 11 in Listing 14.1   jbt.addActionListener(listener );   // Line 12 in Listing 14.1  

When you click the button, the JButton object fires an ActionEvent and passes it to invoke the listener's actionPerformed method to handle the event.

The event object contains information pertinent to the event, which can be obtained using the methods, as shown in Figure 14.5. For example, you can use e.getSource() to obtain the source object in order to determine whether it is a button, a check box, or a radio button. For an action event, you can use e.getWhen() to obtain the time when the event occurs.


[Page 469]
Figure 14.5. You can obtain useful information from an event object.

14.3.1. Inner Class Listeners

A listener class is designed specifically to create a listener object for a GUI component (e.g., a button). The listener class will not be shared by other applications and therefore is appropriately defined inside the frame class as an inner class.

An inner class , or nested class, is a class defined within the scope of another class. The code in Figure 14.6(a) declares two separate classes, Test and A . The code in Figure 14.6(b) declares A as an inner class in Test .

Figure 14.6. Inner classes combine dependent classes into the primary class.


The class InnerClass defined inside OuterClass in Figure 14.6(c) is another example of an inner class. An inner class may be used just like a regular class. Normally, you declare a class an inner class if it is only used by its outer class. An inner class has the following features:


[Page 470]
  • An inner class is compiled into a class named OuterClassName $ InnerClassName .class. For example, the inner class A in Test is compiled into Test$A .class in Figure 14.6(b).

  • An inner class can reference the data and methods defined in the outer class in which it nests , so you do not need to pass the reference of an object of the outer class to the constructor of the inner class. For this reason, inner classes can make programs simple and concise .

  • An inner class can be declared with a visibility modifier subject to the same visibility rules applied to a member of the class.

  • An inner class can be declared static . A static inner class can be accessed using the outer class name . A static inner class cannot access non-static members of the outer class.

  • Objects of an inner class are often created in the outer class. But you can also create an object of an inner class from another class. If the inner class is non-static, you must first create an instance of the outer class, then use the following syntax to create an object for the inner class:

     OuterClass.InnerClass innerObject = outerObject.   new   InnerClass(); 
  • If the inner class is static, use the following syntax to create an object for it:

     OuterClass.InnerClass innerObject =   new   OuterClass.InnerClass(); 

Tip

A simple use of inner classes is to combine dependent classes into a primary class. This reduces the number of source files. It also makes class files easy to organize, since all the class files are named with the primary class as the prefix. For example, rather than creating two source files, Test.java and A.java, in Figure 14.6(a), you can combine class A into class Test and create just one source file, Test.java, in Figure 14.6(b). The resulting class files are Test.class and Test$A.class.


Listing 14.1 can now be modified using an inner class.

Listing 14.2. SimpleEventDemoInnerClass.java


[Page 471]

Listing 14.2 is the same as Listing 14.1 except that the OKListener class is now an inner class. As an inner class, it can conveniently reference data and methods in the frame class. Since the listener class will not be used by applications outside the frame class, it is declared private .

The interaction between the source and the listener is shown in Figure 14.7.

  1. jbtOK registers listener by invoking addActionListener(listener) .

  2. jbtOK invokes listener 's actionPerformed method to process an ActionEvent .

Figure 14.7. The source invokes actionPerformed in the listener ( OKListener ) to handle an ActionEvent .


14.3.2. Anonymous Inner Class Listeners

Inner class listeners can be shortened using anonymous inner classes. An anonymous inner class is an inner class without a name. It combines declaring an inner class and creating an instance of the class in one step. An anonymous inner class is declared as follows:

   new   SuperClassName/InterfaceName() {  // Implement or override methods in superclass or interface   // Other methods if necessary  } 

Since an anonymous inner class is a special kind of inner class, it is treated like an inner class in many ways. In addition, it has the following features:

  • An anonymous inner class must always extend a superclass or implement an interface, but it cannot have an explicit extends or implements clause.

  • An anonymous inner class must implement all the abstract methods in the superclass or in the interface.


    [Page 472]
  • An anonymous inner class always uses the no-arg constructor from its superclass to create an instance. If an anonymous inner class implements an interface, the constructor is Object() .

  • An anonymous inner class is compiled into a class named OuterClassName$ n .class. For example, if the outer class Test has two anonymous inner classes, they are compiled into Test$1.class and Test$2.class.

Listing 14.3 is an example of rewriting the preceding example using anonymous inner classes.

Listing 14.3. SimpleEventDemoAnonymousInnerClass.java
 1   import   javax.swing.*; 2   import   java.awt.event.*; 3   import   java.awt.*; 4 5   public class   SimpleEventDemoAnonymousInnerClass   extends   JFrame { 6   public   SimpleEventDemoAnonymousInnerClass() { 7 JButton jbtOK =   new   JButton(   "OK"   ); 8 setLayout(   new   FlowLayout()); 9 add(jbtOK); 10 11  // Create and register anonymous inner class listener  12 jbtOK.addActionListener(    new   ActionListener() {  13    public void   actionPerformed(ActionEvent e) {  14  System.out.println(   "It is OK"   );  15  }  16  }  ); 17 } 18 19  /** Main method */  20   public static void   main(String[] args) { 21 JFrame frame =   new   SimpleEventDemoAnonymousInnerClass(); 22 frame.setTitle(   "SimpleEventDemoAnonymousInnerClass"   ); 23 frame.setLocationRelativeTo(   null   );  // Center the frame  24 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 25 frame.setSize(   220   ,   80   ); 26 frame.setVisible(   true   ); 27 } 28 } 

The anonymous listener (lines 12 “16) in this example works the same way as the inner class listener in the preceding example. The program is condensed using an anonymous inner class.

Anonymous inner classes are compiled into OuterClassName$#.class , where # starts at 1 and is incremented for each anonymous class encountered by the compiler. In this example, the anonymous inner class is compiled into SimpleEventDemoAnonymousInnerClass$1.class .

Pedagogical Note

Anonymous adapters make programs simple and concise, and enable handlers to access data and methods in the outer class. From here on, this book will use anonymous inner class event adapters to implement listeners.


14.3.3. Example: Handling Simple Action Events

This example writes a program that displays two buttons , OK and Cancel, in a frame. A message is displayed on the console to indicate which button and when it is clicked, as shown in Figure 14.8. The program is given in Listing 14.4.


[Page 473]
Figure 14.8. The program responds to the button action events.


Listing 14.4. TestActionEvent.java
 1   import   javax.swing.*; 2   import   java.awt.*; 3   import   java.awt.event.*; 4 5   public class   TestActionEvent   extends   JFrame { 6   private   JButton jbtOK =   new   JButton(   "OK"   ); 7   private   JButton jbtCancel =   new   JButton(   "Cancel"   ); 8 9   public   TestActionEvent() { 10 setLayout(   new   FlowLayout()); 11 12 add(jbtOK); 13 add(jbtCancel); 14 15  jbtOK.addActionListener(   new   ActionListener()  { 16   public void   actionPerformed(ActionEvent e) { 17 System.out.println(   "The "   + e.getActionCommand() +   " button "   18 +   "is clicked at\n "   +   new   java.util.Date(e.getWhen())); 19 } 20 }); 21 22  jbtCancel.addActionListener(   new   ActionListener() {  23   public void   actionPerformed(ActionEvent e) { 24 System.out.println(   "The "   + e.getActionCommand() +   " button "   25 +   "is clicked at\n "   +   new   java.util.Date(e.getWhen())); 26 } 27 }); 28 } 29 30  /** Main method */  31   public static void   main(String[] args) { 32 TestActionEvent frame =   new   TestActionEvent(); 33 frame.setTitle(   "TestActionEvent"   ); 34 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 35 frame.setSize(   220   ,   80   ); 36 frame.setVisible(  true  ); 37 } 38 } 

The button objects jbtOK and jbtCancel are the source of ActionEvent . Anonymous inner class listeners are used to create listeners for jbtOK and jbtCancel in lines 15 and 22.

Clicking a button causes the actionPerformed method in the listener to be invoked. The e.getActionCommand() method returns the action command from the button (line 17). By default, a button's action command is the text of the button.

The e.getWhen() method returns the time of the action in milliseconds since January 1, 1970, 00:00:00 GMT. The Date class converts the time to year, month, date, hours, minutes, and seconds (line 18).


[Page 474]

14.3.4. Example: Handling Window Events

This example writes a program that demonstrates handling window events. Any subclass of the Window class can fire the following window events: window opened, closing, closed, activated, deactivated, iconified , and deiconified. The program in Listing 14.5 creates a frame, listens to the window events, and displays a message to indicate the occurring event. Figure 14.9 shows a sample run of the program.

Figure 14.9. The window events are displayed on the console when you run the program from a DOS prompt.


Listing 14.5. TestWindowEvent.java
(This item is displayed on pages 474 - 475 in the print version)
 1   import   java.awt.event.*; 2   import   javax.swing.JFrame; 3 4   public class   TestWindowEvent   extends   JFrame { 5   public static void   main(String[] args) { 6 TestWindowEvent frame =   new   TestWindowEvent(); 7 frame.setLocationRelativeTo(   null   );  // Center the frame  8 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 9 frame.setTitle(   "TestWindowEvent"   ); 10 frame.setSize(   220   ,   80   ); 11 frame.setVisible(   true   ); 12 } 13 14   public   TestWindowEvent() { 15 addWindowListener(    new   WindowListener() {  16  /**  17  * Handler for window deiconified event  18  * Invoked when a window is changed from a minimized  19  * to a normal state.  20  */  21    public void   windowDeiconified(WindowEvent event) {  22 System.out.println(   "Window deiconified"   ); 23 } 24 25  /**  26  * Handler for window iconified event  27  * Invoked when a window is changed from a normal to a  28  * minimized state. For many platforms, a minimized window  29  * is displayed as the icon specified in the window's  30  * iconImage property.  31  */  32    public void   windowIconified(WindowEvent event) {  33 System.out.println(   "Window iconified"   ); 34 } 35 36  /**  37  * Handler for window activated event  38  * Invoked when the window is set to be the user 's  39  * active window, which means the window (or one of its  

[Page 475]
 40  * subcomponents) will receive keyboard events.  41  */  42    public void   windowActivated(WindowEvent event) {  43 System.out.println(   "Window activated"   ); 44 } 45 46  /**  47  * Handler for window deactivated event  48  * Invoked when a window is no longer the user's active  49  * window, which means that keyboard events will no longer  50  * be delivered to the window or its subcomponents.  51  */  52    public void   windowDeactivated(WindowEvent event) {  53 System.out.println(   "Window deactivated"   ); 54 } 55 56  /**  57  * Handler for window opened event  58  * Invoked the first time a window is made visible.  59  */  60    public void   windowOpened(WindowEvent event) {  61 System.out.println(   "Window opened"   ); 62 } 63 64  /**  65  * Handler for window closing event  66  * Invoked when the user attempts to close the window  67  * from the window's system menu. If the program does not  68  * explicitly hide or dispose the window while processing  69  * this event, the window close operation will be cancelled.  70  */  71    public void  windowClosing(WindowEvent event) {   72 System.out.println(   "Window closing"   ); 73 } 74 75  /**  76  * Handler for window closed event  77  * Invoked when a window has been closed as the result  78  * of calling dispose on the window.  79  */  80    public void   windowClosed(WindowEvent event) {  81 System.out.println(   "Window closed"   ); 82 } 83  }  ); 84 } 85 } 

The WindowEvent can be fired by the Window class or by any subclass of Window . Since JFrame is a subclass of Window , it can fire WindowEvent .

TestWindowEvent extends JFrame and implements WindowListener . The WindowListener interface defines several abstract methods ( windowActivated , windowClosed , windowClosing , windowDeactivated , windowDeiconified , windowIconified , windowOpened ) for handling window events when the window is activated, closed, closing, deactivated, deiconified, iconified, or opened.

When a window event, such as activation, occurs, the windowActivated method is triggered. Implement the windowActivated method with a concrete response if you want the event to be processed .


[Page 476]

14.3.5. Listener Interface Adapters

Because the methods in the WindowListener interface are abstract, you must implement all of them even if your program does not care about some of the events. For convenience, Java provides support classes, called convenience adapters , which provide default implementations for all the methods in the listener interface. The default implementation is simply an empty body. Java provides convenience listener adapters for every AWT listener interface with multiple handlers. A convenience listener adapter is named X Adapter for X Listener. For example, WindowAdapter is a convenience listener adapter for WindowListener . Table 14.3 lists the convenience adapters.

Table 14.3. Convenience Adapters
Adapter Interface
WindowAdapter WindowListener
MouseAdapter MouseListener
MouseMotionAdapter MouseMotionListener
KeyAdapter KeyListener
ContainerAdapter ContainerListener
ComponentAdapter ComponentListener
FocusAdapter FocusListener

Using WindowAdapter , the preceding example can be simplified as shown in Listing 14.6 if you are only interested in the window activated event. The WindowAdapter class is used to create an anonymous listener instead of WindowListener (line 15). The windowActivated handler is implemented in line 16.

Listing 14.6. TestWindowEvent.java
 1   import   java.awt.event.*; 2   import   javax.swing.JFrame; 3 4   public class   AdapterDemo   extends   JFrame { 5   public static void   main(String[] args) { 6 AdapterDemo frame =   new   AdapterDemo(); 7 frame.setLocationRelativeTo(   null   );  // Center the frame  8 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 9 frame.setTitle(   "AdapterDemo"   ); 10 frame.setSize(   220   ,   80   ); 11 frame.setVisible(   true   ); 12 } 13 14   public   AdapterDemo() { 15  addWindowListener(   new   WindowAdapter() {  16    public void   windowActivated(WindowEvent event) {  17 System.out.println(   "Window activated"   ); 18 } 19 }); 20 } 21 } 

 


Introduction to Java Programming-Comprehensive Version
Introduction to Java Programming-Comprehensive Version (6th Edition)
ISBN: B000ONFLUM
EAN: N/A
Year: 2004
Pages: 503

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