Writing a Simple Bean |
You'll need a good understanding of the JDK 1.1 event mechanism before reading this section. Here's the list of recommended readings:
- The Java AWT 1.1 event handling mechanism
- Chapter 6 of the JavaBeans API Specification
- Section 8.4, Design Patterns for Events of the JavaBeans API Specification.
Beans use the new event mechanism implemented in JDK 1.1, so implementing Bean events is the same as implementing events in any JDK 1.1 component. This section describes how this event mechanism is used by Beans and the BeanBox.
How the BeanBox Discovers a Beans Event Capabilities
The BeanBox uses either design pattern introspection or a
BeanInfo
class to discover what events a Bean can fire.Using Introspection to Discover the Events A Bean Fires
JavaBeans provides event-oriented design patterns to give introspecting tools the ability to discover what events a Bean can fire. For a Bean to be the source of an event, it must implement methods that add and remove listener objects for that type of event. The design patterns for these methods are
public void add<EventListenerType>(<EventListenerType> a) public void remove<EventListenerType>(<EventListenerType> a)These methods let a source Bean know where to fire events. The source Bean then fires events at those listener Beans using the methods for those particular interfaces. For example, if a source Bean registersActionListener
objects, it will fire events at those objects by calling theactionPerformed()
method on those listeners.To see events discovered using design patterns, drop an instance of
OurButton
into the BeanBox and pull down the Edit|Events menu. This displays a list of event interfaces to whichOurButton
can fire events. Note thatOurButton
itself only adds and removes two of these interfaces; the rest are inherited from the base class.Using
BeanInfo
to Define the Events a Bean FiresYou can explicitly "publish" the events a Bean fires by using a class that implements the
BeanInfo
interface. TheExplicitButton
demo Bean subclassesOurButton
, and provides an associatedExplicitButtonBeanInfo
class.ExplicitButtonBeanInfo
implements the following method to explicitly define interfaces to whichExplicitButton
fires events.public EventSetDescriptor[] getEventSetDescriptors() { try { EventSetDescriptor push = new EventSetDescriptor(beanClass, "actionPerformed", java.awt.event.ActionListener.class, "actionPerformed"); EventSetDescriptor changed = new EventSetDescriptor(beanClass, "propertyChange", java.beans.PropertyChangeListener.class, "propertyChange"); push.setDisplayName("button push"); changed.setDisplayName("bound property change"); EventSetDescriptor[] rv = { push, changed}; return rv; } catch (IntrospectionException e) { throw new Error(e.toString()); } }Drop anExplicitButton
instance in the BeanBox, and pull down the Edit|Events menu. Notice that only those interfaces explicitly exposed in theExplicitButtonBeanInfo
class are listed. No inherited capabilities are exposed. See the Using BeanInfo section for more information on the BeanInfo interface.Viewing a Bean's Events in the BeanBox
If you select an
OurButton
Bean in the BeanBox, then pull down the Edit|Events menu, you will see a list of interfaces thatOurButton
can fire events at. Each interface item will, when selected, display the methods that fire different events at those interfaces. These correspond to all the events thatOurButton
can fire.Hooking Up Events in the BeanBox
In this example you will use two OurButton bean instances to stop and start an instance of the animated Juggler bean. You will label the buttons "start" and "stop"; make the start button, when pressed, invoke the Juggler bean's
startJuggling
method; and make the stop button, when pressed, invoke the Juggler bean'sstopJuggling
method.
- Start the BeanBox.
- Drop a
Juggler
bean and twoOurButton
bean instances into the BeanBox.- Select an
OurButton
instance. In the Properties sheet, change the label property to "start". Select the secondOurButton
instance and change its label to "stop".- Select the start button. Choose the Edit|Events|action|actionPerformed menu item. This causes a rubber band line to track between the start button and the cursor. Click on the
Juggler
instance. This brings up theEventTargetDialog
:
This list contains
Juggler
methods that take no arguments, or arguments of typeactionPerformed
.- Select the
startJuggling
method and press OK. You will see a message that the BeanBox is generating adapter classes.- Do the above two steps on the stop button, except choose the
stopJuggling
method in theEventTargetDialog
.Clicking on the start and stop buttons will now start and stop the
Juggler
. Here is a general description of what happened:
- The start and stop buttons, are event sources. Event sources fire events at event targets. In this example the Juggler bean is the event target.
- When you select the start button and choose an event method (via the Edit|Event menu item), you are choosing the type of event the event source will fire.
- When you connect the rubber band line to another bean, you are selecting the event target Bean.
- The
EventTargetDialog
lists methods that can accept that type of event or that take no parameters. When you choose a method in theEventTargetDialog
, you are specifying the method that will receive the fired event, and act on it.You will use this juggler example later when you learn how to generate applets, so use the File|Save menu item to save this example to a file of your choice.
Event Adapter Classes
The BeanBox generates an adapter class the interposes between the source and the target. The adapter class implements the appropriate event listener interface (and so is the actual listener, not the target
Juggler
Bean), catches the event fired by the button, and then calls the selected target method. Here is the BeanBox-generated adapter class that interposes between the start button and theJugglerBean
:// Automatically generated event hookup file. package tmp.sunw.beanbox; import sunw.demo.juggler.Juggler; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; public class ___Hookup_1474c0159e implements java.awt.event.ActionListener, java.io.Serializable { public void setTarget(sunw.demo.juggler.Juggler t) { target = t; } public void actionPerformed(java.awt.event.ActionEvent arg0) { target.startJuggling(arg0); } private sunw.demo.juggler.Juggler target; }The adapter implements the
ActionListener
interface that you selected in the BeanBox's Edit|Events menu.ActionListener
declares one method,actionPerformed()
, which is implemented by the adapter to call the target Bean method that you selected. ThesetTarget()
method is called by the BeanBox to set the target Bean.The
EventMonitor
Demo BeanThe
EventMonitor
Bean (beans/demo/sunw/demo/encapsulatedEvents
) prints out source Bean event reports, as they occur, in a scrolling listbox. To see how this works, take the following steps:When the first event is delivered,
- Drop
OurButton
andEventMonitor
instances in the BeanBox. You might want to resize theEventMonitor
(and the BeanBox) to accommodate viewing the event reports.- Select the
OurButton
instance, and choose any event method in the Edit|Events menu.- Connect the rubber band line to the
EventMonitor
, and choose itsinitiateEventSourcMonitoring
in theEventTargetDialog
.- Select the
OurButton
Bean. You will begin seeing event reports in theEventMonitor
EventMonitor
analyzes the source Bean to discover all the events it fires, creates and registers an event listener for each event type, and then reports whenever any event is fired. This is useful for debugging. Try connecting other demo Beans toEventMonitor
to observer their events.Events for Bound and Constrained Properties
The bound and constrained properties sections describe two specific event listener interfaces.
Writing a Simple Bean |