JMU
Custom Events
in Java


Prof. David Bernstein
James Madison University

Computer Science Department
bernstdh@jmu.edu


Overview
The Basics
An Example
An Example (cont.)

ColorEvent

javaexamples/gui/ColorEvent.java
        package gui;

import java.awt.*;

/**
 * An EventObject that can be used to inform listeners of a 
 * Color change
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public class ColorEvent extends java.util.EventObject
{
    private Color       color;
    private String      id;    
    
    /**
     * Explicit Value Constructor
     *
     * @param source   The source of the event
     * @param color    The Color of interest
     * @param id       The identifier for this ColorEvent
     */
    public ColorEvent(Object source, Color color, String id)
    {
       super(source);
       this.color = color;
       this.id    = id;
    }

    /**
     * Get the Color associated with this ColorEvent
     *
     * @return   The Color
     */
    public Color getColor()
    {
       return color;
    }

    /**
     * Get the ID associated with this ColorEvent
     *
     * @return   The ID
     */
    public String getID()
    {
       return id;
    }
    
}

        
An Example (cont.)

ColorListener

javaexamples/gui/ColorListener.java
        package gui;

/*
 * Requirements of objects that want to be informed of ColorEvents
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public interface ColorListener extends java.util.EventListener
{
    /**
     * Handle a colorChanged message
     *
     * @param event   The ColorEvent that generated the message
     */
    public abstract void colorChanged(ColorEvent event);    
}
        
An Example (cont.)

ColorButton

javaexamples/gui/ColorButton.java
        package gui;

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;



/**
 * A GUI Component that can be used to select a Color
 *
 * A ColorButton displays the currently selected
 * Color.  When clicked, a JColorChooser is displayed that
 * allows the user to select a new Color.
 *
 * Observers that want to be informed of changes in the color
 * should implement the ChangeListener interface (not the ActionListener
 * interface).
 *
 * Because the ColorEvent extends java.util.EventObject (i.e., is a
 * Swing event), this class uses the EventListenerList class to manage
 * listeners.  If ColorEvent were an AWT event, it would use 
 * AWTEventMulticaster instead.  In that case, there would be an attribute
 * like:
 *
 *   private ColorListener      colorListener;
 *
 * the addColorListener() method would look something like:
 *
 *   public void addColorListener(ColorListener listener)
 *   {
 *      // Add the listener to the existing multicast listener
 *      colorListener = AWTEventMulticaster.add(colorListener, listener);
 *   }
 *
 * and the firing code would look something like:
 *
 *   if (colorListener != null)
 *   {
 *        colorListener.colorChaned(event);
 *    }
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public class ColorButton extends JButton implements ActionListener
{
    private Color              color;
    private EventListenerList  listenerList = new EventListenerList();

    private static final Dimension MINIMUM_SIZE   = new Dimension(80,40);
    private static final Dimension PREFERRED_SIZE = new Dimension(80,80);
    

    /**
     * Default Constructor (Constructs a BLACK ColorButton)
     */
    public ColorButton()
    {
       this(Color.BLACK);       
    }
    
    /**
     * Explicit Value Constructor
     *
     * @param color  The starting color
     */
    public ColorButton(Color color)
    {
       super("   ");       
       setColor(color);

       // Listen to ActionEvents
       super.addActionListener(this);       
    }

    /**
     * Add a ColorListener to this ColorButton
     *
     * Note: These listeners are informed of events only after the 
     * dialog stops blocking.
     *
     * @param listener   The ColorListener
     */
    public void addColorListener(ColorListener listener)
    {
       listenerList.add(ColorListener.class, listener);
    }
    
    /**
     * Handle actionPerformed messages (required by ActionListener)
     *
     * @param event  The relevant ActionEvent
     */
    public void actionPerformed(ActionEvent event)
    {
       Color         newColor;       
       Object        source;
       
       source = event.getSource();
       if (this == source)
       {
          newColor = JColorChooser.showDialog(
                                       this, 
                                       "Choose a color.", 
                                       this.color);
          if (newColor != null) setColor(newColor);          
       }

       fireColorEvent();       
    }

    /**
     * Notify all of the ColorListener objects
     */
    protected void fireColorEvent()
    {
       ColorEvent         ce;
       Object[]           list;
       
       list = listenerList.getListenerList();
       if ((list != null) && (list.length > 0))
       {
          ce = new ColorEvent(this, color, getActionCommand());          
          for (int i=0; i<list.length; i++)
          {
             // The array contains ALL types of listeners, so check the class
             if (list[i] instanceof ColorListener)
             {
                ((ColorListener)list[i]).colorChanged(ce);
             }
          }
       }
    }

    /**
     * Get the current Color
     *
     * @return  The Color
     */
    public Color getColor()
    {
       return this.color;       
    }
    
    /**
     * Render this ColorButton
     *
     * @param g   The rendering engine to use
     */
    public void paint(Graphics g)
    {
       Dimension     d;
       int           height, width, x, y;
       
       super.paint(g);

       d      = getSize();
       height = d.height / 2;       
       width  = d.width  / 2;
       
       x = d.width/2  - width/2;
       y = d.height/2 - height/2;
       
       g.setColor(this.color);
       g.fillRect(x, y, width, height);
       g.drawRect(x, y, width, height);
    }

    /**
     * Remove a ColorListener
     *
     * @param listener   The ColorListener
     */
    public void removeColorListener(ColorListener listener)
    {
       listenerList.remove(ColorListener.class, listener);
    }

    /**
     * Set the current Color
     *
     * @param  The Color
     */
    public void setColor(Color color)
    {
       if (color != null) this.color = color;
    }
}
        
An Example (cont.)

An Application

javaexamples/gui/ColorButtonDriver.java
        import java.awt.*;
import javax.swing.*;

import gui.ColorButton;
import gui.ColorEvent;
import gui.ColorListener;

/**
 * A driver that  illustrates the use of the ColorButton class
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
  */
public class ColorButtonDriver implements ColorListener
{
    /**
     * Handle a colorChanged message (requried by ColorListener)
     *
     * @param event   The ColorEvent that generated the message
     */
    public void colorChanged(ColorEvent event)
    {
       System.out.println(event.getID() + "\t"+ event.getColor());
    }
    
    /**
     * The entry point
     */
    public static void main(String[] args)
    {
       ColorButton               button;       
       ColorButtonDriver         cbd;
       Container                 contentPane;
       JFrame                    frame;
       
       frame = new JFrame();
       contentPane = frame.getContentPane();
       contentPane.setLayout(new FlowLayout());

       cbd = new ColorButtonDriver();

       button = new ColorButton(Color.RED);
       button.setActionCommand("Foreground");       
       button.addColorListener(cbd);
       contentPane.add(button);
       
       button = new ColorButton(Color.BLUE);
       button.setActionCommand("Background");       
       button.addColorListener(cbd);
       contentPane.add(button);
       
       frame.setSize(400,200);
       frame.setVisible(true);
    }
    
}