javabeans event handling and properties. event handling and properties handling bean events event...
Post on 21-Dec-2015
274 views
TRANSCRIPT
Event Handling and Properties
Handling Bean Events
Event Objects, Listeners, and Sources
Event Adapters
Property Management
Indexed, Bound and Constrained Properties
Introspection - Design Patterns
Explicitly Defining Bean Information
Java Event Model
Events Are Objects In Java
JavaBeans Model based on Event Handling introduced in Java 1.1 API
Event Objects Are Generated By Components for Communication between Beans
Events Propagate from Source to Target Listener Objects
java.util package provides base classes
Event Objects
Base class: java.util.EventObject
public EventObject(Object source)
Encapsulates information about event
References Source of Event
Create Event-Specific Subclasses of EventObject
EventObject Examplepublic class VoltsChangedEvent extends java.util.EventObject{
protected double theVolts;
public VoltsChangedEvent(Object source, double volts){
super(source);theVolts = volts;
}public double getVolts(){
return theVolts;}
}
AWTEvent Classes
KeyEvent MouseEvent ContainerEvent ComponentEvent ActionEvent ItemEvent WindowEvent AdjustmentEvent
PropertyChangeEvent
java.beans package Sent when bound or constrained properties are
altered JavaBeans must generate and send
PropertyChangeEvent objects
Listener Objects Listeners receive events from source objects
Methods are invoked on the listener and event object is passed as a parameter
To receive event notification, a class implements a listener interface
Listener Interface Base class: java.util.EventListener
An event fired by a source object will cause the associated method of the listener object to be called
EventListener Example
public interface VoltsChangeListener extends java.util.EventListener
{void voltsChanged(VoltsChangedEvent e);
}
Some AWT Listener Interfaces & Methods
ActionListenerpublic void actionPerformed(ActionEvent e);
ItemListenerpublic void itemStateChanged(ItemEvent e);
MouseListenerpublic void mouseClicked(MouseEvent e);
public void mouseEntered(MouseEvent e);
public void mouseExited(MouseEvent e);
public void mousePressed(MouseEvent e);
public void mouseReleased(MouseEvent e);
Java Beans Listeners
java.beans.PropertyChangeListener
Bound Properties public void propertyChange(PropertyChangeEvent e);
java.beans.VetoableChangeListener
Constrained Properties public void vetoableChange(PropertyChangeEvent e) throws
PropertyVetoException;
Event Sources
Objects that fire events Register and Unregister Listeners Registration Design Patterns
public void addEventNameListener (EventNameListener l);
public void removeEventNameListener (EventNameListener l);
public EventNameListener[] getEventNameListeners ();
Unicast and Multicast Event Delivery
Multicast - Multiple Listeners Registered with Single Event Source
Unicast - Only one Listener Registered with Single Event Source
Unicast Registration Design Patternspublic void addEventNameListener (EventNameListener l) throws java.util.TooManyListenersException;
public void removeEventNameListener (EventNameListener l);
public EventNameListener getEventNameListener ();
Event Source Example
import java.util.Vector;public class Battery {
protected double currentVolts = 12.0;private Vector voltsChangeListeners = new Vector();
public Battery(double initVoltage){ currentvolts = initVoltage; }
public Battery() {}
Event Source Example - Continued
public synchronized void addVoltsChangeListener(VoltsChangeListener l){
if (!voltsChangeListeners.contains(l))voltsChangeListeners.addElement(l);
}
public synchronized void removeVoltsChangeListener(VoltsChangeListener l){
if (voltsChangeListeners.contains(l))voltsChangeListeners.removeElement(l);
}
Event Source Example - Continued
public synchronized VoltsChangeListener[] getVoltsChangeListeners(){
return (VoltsChangeListener []) voltsChangeListeners.toArray(
new VoltsChangeListener[ voltsChangeListeners.size()]);}
Event Source Example - Continued
protected void notifyVoltsChange(){
VoltsChangedEvent e = new VoltsChangedEvent(this, currentVolts);
Vector v;synchronized(this) {
v = (Vector) voltsChangeListeners.clone();}int cnt = v.size();
for(int i = 0; i < cnt; i++) {
VoltsChangeListener list =(VoltsChangeListener)v.elementAt(i);
list.voltsChanged(e);}
}} // delimits Class definition
Registering an AWT Listener Object
Use the add<event>Listener() method to register a qualified listener with a specific source object
Appropriate add<event>Listener() methods are available to source components which trigger the specific events
This example shows that the argument of the method is the listener object
button.addActionListener(this);
The Recharger Classpublic class Recharger implements VoltsChangeListener{
protected Battery theBattery;
public Recharger(Battery b) {
theBattery = b;theBattery.addVoltsChangeListener(this);
}
public void voltsChanged(VoltsChangedEvent e){
// turn the charging switch on or off}
}
Event Adapters
Listener code could get unmanageable
Listener may want to receive several different event source objects
Listener may want to listen to several objects generating the same event
Handling Events with Adapters
Event Source
Event Adapter
Event Listener
Event Object
Event Object
Fire Event
Forward Event
CreateAdapter
RegisterListener
Single Instance Generic Adapter
Event ListenerHandler1() Handler2() Handler3()
Adapter
Event Source1
Event Source2
Event Source3
ForwardEvents
FireEvents
Implementing a Dispatch Table using Java Reflection
Target makes an instance of the Adapter
Adapter discovers the target class at runtime
Adapter discovers the target methods at runtime
Adapter can invoke the target method
Finding the Class
Battery b = new Battery(12.5);Recharger rech = new Recharger(b);try {
Class theClass = rech.getClass();}
catch(java.lang.ClassNotFoundException e) {}
ALSO:
Class theClass = Recharger.class;
Finding the Method
void setName(String s);
Battery b = new Battery(12.5);Recharger rech = new Recharger(b);try {
Class theClass = rech.getClass();Class paramClasses[] = { java.lang.String.class };java.lang.reflect.Method m =
theClass.getMethod(“setName”,paramClasses);Object param[] = { new String(“Recharger One”) };m.invoke(rech, param);}
catch(Exception e) {}
Assume a setName method for the Recharger class with the following signature:
Generic Voltage Adapter
Handles multiple Battery objects as event sources
Maps to arbitrary target object, an instance of Recharger
Dispatch methods all have the same signature:public void <methodName> (VoltsChangedEvent e);
Voltage Adapter Exampleimport java.lang.reflect.*;import java.util.*;
public class GenericVoltageAdapter implements VoltsChangeListener
{protected Object theTarget;protected Class theTargetClass;protected final static Class paramClass[] =
{ VoltsChangedEvent.class };protected Hashtable map = new Hashtable();
public GenericVoltageAdapter(Object target){ theTarget = target; theTargetClass = target.getClass(); }
Voltage Adapter Example - Continued
public void registerEventHandler (Battery bat, String methodName) throws NoSuchMethodException{Method m = theTargetClass.getMethod(methodName, paramClass);bat.addVoltsChangeListener(this);map.put(bat, m);}
public void voltsChanged(VoltsChangedEvent e) {try {
Method m = (Method)map.get(e.getSource());Object params[] = { e };m.invoke(theTarget, params);}catch (Exception e) {System.out.println(e);} }
Revised Recharger Classpublic class Recharger{
protected Battery battOne;protected Battery battTwo;protected GenericVoltageAdapter voltAdapter;public Recharger(Battery b1, Battery b2) {
battOne = b1; battTwo = b2;voltAdapter = new GenericVoltageAdapter(this);voltAdapter.registerEventHandler(battOne, “volts1”);voltAdapter.registerEventHandler(battTwo, “volts2”);
}// do something specific to battery1 changespublic void volts1(VoltsChangedEvent e) { }// do something specific to battery2 changes public void volts2(VoltsChangedEvent e) { }
}
Properties in JavaBeans
Data Portion of Bean
Define Behavior and State
Exposed to Visual Programming Tools for Customization
Can Be Any Data Type
NOT a one-to-one correspondence between Properties and data members of a class
Accessor Methods
Getter and Setter Methods
Only Getter -> Read-only property
Only Setter -> Write-only property
Design Patterns:public void set<PropertyName> (<PropertyType> x);
public <PropertyType> get<PropertyName>();
Boolean Property Design Pattern for Getter: public boolean is<PropertyName>();
Accessor Methods Example
import java.util.Vector;public class Battery {
protected double currentVolts = 12.0;private Vector voltsChangeListeners = new Vector();
// Constructors Here
public double getCurrentVoltage() {return currentVolts; }
public void setCurrentVoltage(double v) {currentVolts = v;// other processing}
Indexed Properties Ordered collection of values associated with one
name
Implemented as an array
Design Patterns for accessing all elements:public void set<PropertyName> (<PropertyType>[] x);
public <PropertyType>[] get<PropertyName>();
Design Patterns for accessing single element:public void set<PropertyName> (int index, <PropertyType> x);
public <PropertyType> get<PropertyName>(int index);
Indexed Properties Examplepublic class Recharger{
protected Battery[] battArray;public void setBatteries(Battery[] b) {
battArray = b; }public Battery[] getBatteries() {
return battArray; } public void setBatteries(int index, Battery b) {
battArray[index] = b; }public Battery getBatteries(int index) {
return battArray[index]; }
}
Bound Properties Support change notifications
Non-specific property binding
PropertyChangeEvent
PropertyChangeListener
Design Patterns for registering and unregistering listeners for Bound Properties
public void addPropertyChangeListener(PropertyChangeListener l);
public void removePropertyChangeListener(PropertyChangeListener l);
PropertyChangeEvent
ConstructorPropertyChangeEvent(Object source, String propName, Object oldValue, Object newValue);
Methodspublic Object getNewValue();
public Object getOldValue();
public Object getPropagationId();
public String getPropertyName();
public void setPropagationId(Object propID);
PropertyChangeListener
public interface PropertyChangeListener extends EventListener {
public void propertyChange(PropertyChangeEvent e);}
Bound Property Exampleimport java.util.Vector;import java.beans.*;public class Battery {
protected double currentVolts = 12.0;protected Vector propChangeListeners = new Vector();
public Battery(double initVoltage){ currentvolts = initVoltage; }
public Battery() {}
Bound Property Example - Continued
public synchronized void addPropertyChangeListener(PropertyChangeListener l){
if (!propChangeListeners.contains(l))propChangeListeners.addElement(l);
}
public synchronized void removePropertyChangeListener(PropertyChangeListener l){
if (propChangeListeners.contains(l))propChangeListeners.removeElement(l);
}
Bound Property Example - Continued
protected void notifyVoltsChange(){
PropertyChangedEvent e = new PropertyChangedEvent(this, “CurrentVoltage”,
null, new Double(currentVolts));Vector v;synchronized(this) {
v = (Vector) propChangeListeners.clone();}int cnt = v.size();
for(int i = 0; i < cnt; i++) {
PropertyChangeListener list =(PropertyChangeListener)v.elementAt(i);
list.propertyChange(e);}}
} // delimits Class definition
Revised Recharger Classpublic class Recharger implements PropertyChangeListener{
protected Battery theBattery;public Recharger(Battery b) {
theBattery = b;theBattery.addPropertyChangeListener(this);
}public void propertyChange(PropertyChangeEvent e){
if(e.getSource() == theBattery && e.getPropertyName() == “CurrentVoltage”){ Battery b = (Battery)e.getSource(); Object o = e.getNewValue(); double newVoltage; if ( o == null ) newVoltage = b.getCurrentVoltage(); else newVoltage = ((Double)o).doubleValue(); }
}}
PropertyChangeSupportimport java.util.Vector;import java.beans.*;public class Battery extends PropertyChangeSupport {
protected double currentVolts = 12.0;
public Battery(double initVoltage){ this(); currentvolts = initVoltage; }
public Battery() { super(this);}public double getCurrentVoltage() {
return currentVolts; }protected void notifyVoltsChange() {
firePropertyChange(“CurrentVoltage”, null,new Double(currentVolts)); }
}
Constrained Properties Enable Outside Party Validation
VetoableChangeListener
Design Patterns for registering and unregistering listeners for Constrained Properties
public void addVetoableChangeListener(VetoableChangeListener l);
public void removeVetoableChangeListener(VetoableChangeListener l);
PropertyVetoException
Design Patterns for setting and getting Constrained Properties
public <PropertyType> get<PropertyName>();
public void set<PropertyName>(<PropertyType> v) throws PropertyVetoException
Using Bound & Constrained Properties
When Change is Vetoed, New Event must be fired
Listeners cannot assume universal acceptance of constrained property
Properties can be both Bound and Constrained
Fire VetoableChangeEvent
Change Property Value if no veto
Fire PropertyChangeEvent
Constrained Property Example
public class Recharger implements PropertyChangeListener{
protected Battery theBattery;protected double minVoltage = 12.0;protected VetoableChangeSupport;public Recharger(Battery b) {
theBattery = b;theBattery.addPropertyChangeListener(this);vSupport = new VetoableChangeSupport(this);
}public void addVetoableChangeListener(VetoableChangeListener l){vSupport.addVetoableChangeListener(l);}
public void removeVetoableChangeListener(VetoableChangeListener l){vSupport.removeVetoableChangeListener(l);}
Constrained Property Example - Continued
public double getMinimumVoltage(){
return minVoltage;}
public void setMinimumVoltage(double v) throws PropertyVetoException{
if (v < 6.0) throw new PropertyVetoException();
vSupport.fireVetoableChange(“MinimumVoltage”,new Double(minVoltage), new Double(v));
minVoltage = v;
}} // delimits class definition
Listeners for Specific Properties
Design Patterns for registering and unregistering listeners for specific Bound Properties
public void add<PropertyName>Listener(PropertyChangeListener l);
public void remove<PropertyName>Listener(PropertyChangeListener l);
Design Patterns for registering and unregistering listeners for specific Constrained Properties
public void add<PropertyName>Listener(VetoableChangeListener l);
public void remove<PropertyName>Listener(VetoableChangeListener l);
Introspection
Beans expose information about how they work
Application builder tools analyze these features
Low-Level Services: Reflection Facilities
High-Level Services: Limited to Public Properties, Methods, and Events
Design Patterns
Design Patterns Review
Property Design Patterns Simple
public <PropertyType> get<PropertyName>();public void set<PropertyName>(<PropertyType> x);
Booleanpublic boolean is<PropertyName>();
Indexedpublic <PropertyElement> get<PropertyName>(int i);public void set<PropertyName>(int i, <PropertyElement> x);public <PropertyElement> [] get<PropertyName>();public void set<PropertyName>(<PropertyElement>[] x);
Design Patterns Review - Continued
Event Design Patterns Multicast
public void add<EventListenerType>(<EventListenerType> x);public void remove<EventListenerType>(<EventListenerType> x);public <EventListenerType>[] get<EventListenerType>s();
Unicastpublic void add<EventListenerType>(<EventListenerType> x)
throws TooManyListeners;
Method Design Patterns None specified
Explicitly Providing Bean Information
Alternative to Automatic Introspection
Option for controlling Bean Information
Can be used in combination with Automatic Introspection
BeanInfo interface
The Introspector
java.beans.Introspector class
Obtains Bean Information
Two-tier approach
Looks for explicit information
Uses Reflection Techniques combined with Design Patterns
The BeanInfo Interface Implemented by Bean Information Class
Methods gather information about Bean
Design Pattern: JavaBean class name: Car Associated BeanInfo class name: CarBeanInfo
Advantage: Bean does not carry extra baggage
Disadvantage: Tight Coupling Relying on Design Pattern
BeanInfo Interface Methods
public BeanInfo[] getAdditionalBeanInfo(): returns additional BeanInfo objects relevant to the main Bean
public BeanDescriptor getBeanDescriptor(): returns Bean Descriptorpublic int getDefaultEventIndex(): returns default event indexpublic int getDefaultPropertyIndex(): returns default property indexpublic EventSetDescriptor[] getEventSetDescriptors(): returns event set
descriptorspublic Image getIcon(int iconkind): returns specified iconpublic MethodDescriptor[] getMethodDescriptors(): returns method
descriptorspublic PropertyDescriptor[] getPropertyDescriptors(): returns property
descriptors
SimpleBeanInfo class
Implements BeanInfo interface
Derive your own BeanInfo class by extending SimpleBeanInfo
Additional convenience method:public Image loadImage(String resourceName);
Bean Descriptor
Describes class that implements the Bean
Constructor:public BeanDescriptor(Class beanClass);
Some FeatureDescriptor methods:public void setDisplayName(String dispName);
public String getDisplayName();
Bean Descriptor Example
import java.beans.*;
public class RechargerBeanInfo extends SimpleBeanInfo{
public BeanDescriptor getBeanDescriptor(){BeanDescriptor bd = new BeanDescriptor(Recharger.class);bd.setDisplayName(“Simulated Recharger”);return bd;}
}
Setting Bean Icons Icons used in Palettes or Tool Bars
Four supported .GIF formats
Icon Constant
16 x 16 color ICON_COLOR_16x1632 x 32 color ICON_COLOR_32x3216 x 16 monochrome ICON_MONO_16x1632 x 32 monochrome ICON_MONO_32x32
Setting Bean Icons - Example
import java.beans.*;import java.awt.Image;
public class RechargerBeanInfo extends SimpleBeanInfo{
public Image getIcon(int iconKind){if(iconKind == BeanInfo.ICON_COLOR_16x16) {
Image img = loadImage(“recharger.gif”);return img; }
return null;}
}