Implementing Event Sources

   


In the last section of this chapter, we show you how to implement a class that generates its own events and notifies interested listeners. This is occasionally necessary when you use advanced Swing components. It is also interesting to see what goes on behind the scenes when you add a listener to a component.

Our event source will be a PaintCountPanel that counts how often the paintComponent method was called. Every time the count is incremented, the PaintCountPanel notifies all listeners. In our sample program, we will attach just one listener that updates the frame title see Figure 8-11.

Figure 8-11. Counting how often the panel is painted


Whenever you define an event source, you need three ingredients:

  • an event type. We could define our own event class, but we will simply use the existing PropertyChangeEvent class.

  • an event listener interface. Again, we could define our own interface, but we will use the existing PropertyChangeListener interface. That interface has a single method.

     public void propertyChange(PropertyChangeEvent event) 

  • methods for adding and removing listeners. We will supply two methods in the PaintCountPanel class:

     public void addPropertyChangeListener(PropertyChangeListener listener) public void removePropertyChangeListener(PropertyChangeListener listener) 

How do we make sure that events are sent to interested parties? This is the responsibility of the event source. It must construct an event object and pass it to the registered listeners whenever an event occurs.

Event management is a common task, and the Swing designers provide a convenience class, EventListenerList, to make it easy to implement the methods for adding and removing listeners and for firing events. The class takes care of the tricky details that can arise when multiple threads attempt to add, remove, or dispatch events at the same time.

Because some event sources accept listeners of multiple types, each listener in the event listener list is associated with a particular class. The add and remove methods are intended for the implementation of addXxxListener methods. For example,

 public void addPropertyChangeListener(PropertyChangeListener listener) {    listenerList.add(PropertyChangeListener.class, listener); } public void removePropertyChangeListener(PropertyChangeListener listener) {    listenerList.remove(PropertyChangeListener.class, listener); } 

NOTE

You may wonder why the EventListenerList doesn't simply check which interface the listener object implements. But an object can implement multiple interfaces. For example, it is possible that listener happens to implement both the PropertyChangeListener and the ActionListener interface, but a programmer may choose only to add it as a PropertyChangeListener by calling the addPropertyChangeListener. The EventListenerList must respect that choice.


Whenever the paintComponent method is called, the PaintCountPanel class constructs a PropertyChangeEvent object, specifying the event source, the property name, and the old and new property values. It then calls the firePropertyChangeEvent helper method.

 public void paintComponent(Graphics g) {    int oldPaintCount = paintCount;    paintCount++;    firePropertyChangeEvent(new PropertyChangeEvent(this,       "paintCount", oldPaintCount, paintCount));    super.paintComponent(g); } 

The firePropertyChangeEvent method locates all registered listeners and calls their propertyChange methods.

 public void firePropertyChangeEvent(PropertyChangeEvent event) {    EventListener[] listeners = listenerList.getListeners(PropertyChangeListener.class);    for (EventListener l : listeners)       ((PropertyChangeListener) l).propertyChange(event); } 

Example 8-7 shows the source code of a sample program that listens to a PaintCountPanel. The frame constructor adds a property change listener to the panel that updates the frame title:

 panel.addPropertyChangeListener(new    PropertyChangeListener()    {       public void propertyChange(PropertyChangeEvent event)       {          setTitle("EventSourceTest - " + event.getNewValue());       }    }); 

This ends our discussion of event handling. In the next chapter, you will learn more about user interface components. Of course, to program user interfaces, you will put your knowledge of event handling to work by capturing the events that the user interface components generate.

Example 8-7. EventSourceTest.java
  1. import java.awt.*;  2. import java.awt.event.*;  3. import java.util.*;  4. import javax.swing.*;  5. import java.beans.*;  6.  7. public class EventSourceTest  8. {  9.    public static void main(String[] args) 10.    { 11.       EventSourceFrame frame = new EventSourceFrame(); 12.       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 13.       frame.setVisible(true); 14.    } 15. } 16. 17. /** 18.    A frame that contains a panel with drawings 19. */ 20. class EventSourceFrame extends JFrame 21. { 22.    public EventSourceFrame() 23.    { 24.       setTitle("EventSourceTest"); 25.       setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); 26. 27.       // add panel to frame 28. 29.       final PaintCountPanel panel = new PaintCountPanel(); 30.       add(panel); 31. 32.       panel.addPropertyChangeListener(new 33.          PropertyChangeListener() 34.          { 35.             public void propertyChange(PropertyChangeEvent event) 36.             { 37.                setTitle("EventSourceTest - " + event.getNewValue()); 38.             } 39.          }); 40.    } 41. 42.    public static final int DEFAULT_WIDTH = 400; 43.    public static final int DEFAULT_HEIGHT = 200; 44. } 45. 46. /** 47.    A panel that counts how often it is painted. 48. */ 49. class PaintCountPanel extends JPanel 50. { 51.    public void paintComponent(Graphics g) 52.    { 53.       int oldPaintCount = paintCount; 54.       paintCount++; 55.       firePropertyChangeEvent(new PropertyChangeEvent(this, 56.          "paintCount", oldPaintCount, paintCount)); 57.       super.paintComponent(g); 58.    } 59. 60.    /** 61.       Adds a change listener 62.       @param listener the listener to add 63.    */ 64.    public void addPropertyChangeListener(PropertyChangeListener listener) 65.    { 66.       listenerList.add(PropertyChangeListener.class, listener); 67.    } 68. 69.    /** 70.       Removes a change listener 71.       @param listener the listener to remove 72.    */ 73.    public void removePropertyChangeListener(PropertyChangeListener listener) 74.    { 75.       listenerList.remove(PropertyChangeListener.class, listener); 76.    } 77. 78.    public void firePropertyChangeEvent(PropertyChangeEvent event) 79.    { 80.       EventListener[] listeners = listenerList.getListeners(PropertyChangeListener.class); 81.       for (EventListener l : listeners) 82.          ((PropertyChangeListener) l).propertyChange(event); 83.    } 84. 85.    public int getPaintCount() 86.    { 87.       return paintCount; 88.    } 89. 90.    private int paintCount; 91. } 


 javax.swing.event.EventListenerList 1.2 

  • void add(Class t, EventListener l)

    adds an event listener and its class to the list. The class is stored so that event firing methods can selectively call events. Typical usage is in an addXxxListener method:


    public void addXxxListener(XxxListener l)
    {
       listenerList.add(XxxListener.class, l);
    }

    Parameters:

    t

    The listener type

     

    l

    The listener


  • void remove(Class t, EventListener l)

    removes an event listener and its class from the list. Typical usage is in a removeXxxListener method:


    public void removeXxxListener(XxxListener l)
    {
       listenerList.remove(XxxListener.class, l);
    }

    Parameters:

    t

    The listener type

     

    l

    The listener


  • EventListener[] getListeners(Class t) 1.3

    returns an array of all the listeners of the given type. The array is guaranteed to be non-null.

  • Object[] getListenerList()

    returns an array whose elements with an even-numbered index are listener classes and whose elements with an odd-numbered index are listener objects. The array is guaranteed to be non-null.


 java.beans.PropertyChangeEvent 1.1 

  • PropertyChangeEvent(Object source, String name, Object oldValue, Object newValue)

    constructs a property change event.

    Parameters:

    source

    The event source, that is, the object that reports a property change

     

    name

    The name of the property

     

    oldValue

    The value of the property before the change

     

    newValue

    The value of the property after the change



 java.beans.PropertyChangeListener 1.1 

  • void propertyChange(PropertyChangeEvent event)

    called when a property value has changed.


       
    top



    Core Java 2 Volume I - Fundamentals
    Core Java(TM) 2, Volume I--Fundamentals (7th Edition) (Core Series) (Core Series)
    ISBN: 0131482025
    EAN: 2147483647
    Year: 2003
    Pages: 132

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