Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Bean Communication COMP434B Software Design • Events are the primary mechanism by which Java components interact with each other • One Bean generates an event and one or more other Beans receive it JavaBeans: Events and Reflection • Java 1.0 event model was based on the component containment hierarchy • If a component didn’t handle a particular event then it propagated up to the containing component • Simple - OK for writing basic applets • Doesn’t scale well to complicated interfaces 2 Bean Communication • Java 1.1 delegation event model… • Provides a standard mechanism for a source to generate an event and send it to a set of listeners • Event • An object that describes some state change in a source • Can be generated when a user interacts with an element in a GUI Eg pressing a button, moving a slider, dragging the mouse etc • Events may also be generated that are not directly caused by user input Bean Communication • Java 1.1 delegation event model… • A source - generate events • Sources have three main responsibilities: • Provide methods that allow listeners to register and deregister for notifications about a specific type of event • Generate events • Send events to all registered listeners Multiple listeners - multicasting Single listener - unicasting Eg arrival of incoming data, expiration of a software timer, overflow of a buffer 3 Bean Communication • Java 1.1 delegation event model… • Registering and deregistering methods: public void addTypeListener( TypeListener el) public void addTypeListener( TypeListener el) throws TooManyListenersException Public void removeTypeListener(TypeListener el) • Type is the type of the event, and el is the event listener • Eg. javax.swing.AbstractButton • Provides common behaviours for buttons and menu items (subclasses: JButton, JMenuItem, JToggleButton) • Generates an action event when pressed/selected 4 Bean Communication • Java 1.1 delegation event model… • A listener - receives event notifications • Listeners have three main responsibilities • Register to receive notifications about specific events Call appropriate registration method of the source • Implement an interface to receive events of that type • Deregister if it no longer wants to receive notifications about a specific type of event Call appropriate deregistration method of the source • public void addActionListener(ActionListener al) • public void removeActionListener(ActionListener al) 5 6 1 Bean Communication Bean Communication • Event classes… • A set of classes is provided to represent the various types of UI events (AWT events) Object • Eg. ActionListener interface provides one method to receive action events void actionPerformed(ActionEvent ae) • ae is the ActionEvent object generated by the source • When a button is pressed, the actionPerformed method of all registered listeners is invoked and the event is passed as an argument to that method EventObject AWTEvent ActionEvent ContainerEvent ComponentEvent FocusEvent InputEvent KeyEvent 7 Bean Communication • Event classes… AdjustmentEvent ItemEvent PaintEvent TextEvent WindowEvent 8MouseEvent Bean Communication • Event classes… • EventObject class extends Object • AWTEvent class extends EventObject • Is part of the java.util package • Is the superclass of all event state objects • Constructor : EventObject(Object source) • Is part of the java.awt package • All AWT event types are subclasses of AWTEvent • One of its constructors: AWTEvent(Object source, int Source is the object that generates the event id) Source is the object generating the event, id identifies the type of event • Has two methods : • Two frequently used methods: Object getSource() - return the generating object String toString() - return a String equivalent of the event int getId() String toString() 9 10 Bean Communication AWT Events Examples • Action and Item Events • Listener interfaces • EventListener interface is part of the java.util package • It does not define any constants or methods, but exists only to identify those interfaces that process events • All event listener interfaces must extend this interface • Events typically have a corresponding listener interface • BlahEvent - BlahListener 11 • Usually generated when buttons are pressed and menu items are selected respectively package actionevents; import java.awt.*; import javax.swing.JButton; public class ActionSource1 extends JButton { public ActionSource1() { super("ActionSource1"); } } 2 package actionevents; import java.awt.*; import java.awt.event.*; import javax.swing.JTextArea; import javax.swing.JPanel; package actionevents; import java.awt.*; import javax.swing.JComboBox; public class ActionReceiver extends JPanel implements ActionListener, ItemListener { private JTextArea ta; public class ActionSource2 extends JComboBox { public ActionSource2() { addItem("Item 1"); addItem("Item 2"); addItem("Item 3"); } public ActionReceiver() { ta = new JTextArea(10,20); add(ta); } } . . . public void actionPerformed(ActionEvent ae) { String ac = ae.getActionCommand(); int modifiers = ae.getModifiers(); String s = ac; if((modifiers & ActionEvent.ALT_MASK) != 0) { s += ", ALT_MASK"; } if((modifiers & ActionEvent.CTRL_MASK) != 0) { s += ", CTRL_MASK"; } if((modifiers & ActionEvent.META_MASK) != 0) { s += ", META_MASK"; } if((modifiers & ActionEvent.SHIFT_MASK) != 0) { s += ", SHIFT_MASK"; } ta.append(s + "\n"); } public void itemStateChanged(ItemEvent e) { String item = (String)e.getItem(); String info = (e.getStateChange() == ItemEvent.SELECTED) ? " (selected)" : " (deselected)"; ta.append(item+info+"\n"); } } . . . public class ActionEventsDemo { public static void main(String [] args) { . . . ActionSource1 as1 = new ActionSource1(); ActionSource2 as2 = new ActionSource2(); ActionReceiver ar = new ActionReceiver(); . . . if (mode == 1) { as1.setBounds(10,10,150,30); jf.getContentPane().add(as1); as1.addActionListener(ar); } else { as2.setBounds(10,10,150,30); jf.getContentPane().add(as2); as2.addActionListener(ar); as2.addItemListener(ar); } . . . AWT Events Examples • Mouse Events • Are generated when the mouse is clicked, dragged, moved, pressed or released (also when mouse pointer enters or exits a component) • MouseEvent class defines many int constants • MOUSE_CLICKED, MOUSE_DRAGGED, MOUSE_ENTERED, MOUSE_EXITED etc • Some commonly used methods of MouseEvent: • Point getPoint() - returns a Point object encapsulating the position of the mouse • getX(), getY() - return the x and y coordinates of the mouse • Two listener interfaces - MouseListener and MouseMotionListener 18 3 package mouseevents; import java.awt.*; import javax.swing.JPanel; public class MouseSource extends JPanel { public MouseSource() { Dimension d = new Dimension(100,100); setMinimumSize(d); setPreferredSize(d); setMaximumSize(d); } public void paintComponent(Graphics g) { super.paintComponent(g); Dimension d = getSize(); g.drawRect(0, 0, d.width – 1, d.height – 1); } } public void mouseEntered(MouseEvent me) { ta.append("mouse entered\n"); } public void mouseExited(MouseEvent me) { ta.append("mouse exited\n"); } public void mousePressed(MouseEvent me) { ta.append("mouse pressed\n"); } public void mouseReleased(MouseEvent me) { ta.append("mouse released\n"); } public void mouseDragged(MouseEvent me) { ta.append("mouse dragged\n"); } public void mouseMoved(MouseEvent me) { ta.append("mouse moved\n"); } package mouseevents; import java.awt.*; import java.awt.event.*; import javax.swing.JPanel; import javax.swing.JTextArea; import javax.swing.JScrollPane; public class MouseReceiver extends JPanel implements MouseListener, MouseMotionListener { private JTextArea ta; public MouseReceiver() { ta = new JTextArea(15, 40); JScrollPane js = new JScrollPane(ta); add(js); } public void mouseClicked(MouseEvent me) { ta.append("mouse clicked\n"); } . . . Adapter Classes • An adapter class provides empty implementations of all methods defined in a specific event listener interface • Useful if you only want to process a subset of the events that are received by a particular interface • MouseListener has five methods. If for example you only wanted to process mouseClicked() then your class could extend MouseAdapter and overide only the mouseClicked method • Can’t be used in this way if your class already extends some other class } 22 Anonymous Inner Classes • An inner class is one that is defined within the scope of another class • Has access to all the variables and methods of the enclosing class • An anonymous inner class is one that does not have a name • Use when you only ever need one object of the class • Can be extremely useful when writing code to process events 23 package dot; import java.awt.*; import java.awt.event.*; import javax.swing.JPanel; public class Dot extends JPanel { private Point p; public Dot() { Dimension d = new Dimension(200, 200); setMinimumSize(d); setPreferredSize(d); setMaximumSize(d); p = new Point(100, 100); addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent me) { changePoint(me.getPoint()); } }); } . . . 4 public void changePoint(Point newP) { p = newP; repaint(); } public void paintComponent(Graphics g) { super.paintComponent(g); Dimension d = getSize(); g.drawRect(0, 0, d.width – 1, d.height – 1); g.fillRect(p.x – 2, p.y – 2, 4, 4); } Dynamic Event Handlers • java.beans.EventHandler (introduced in Java 1.3) • Provides support for dynamically generating event listeners • Can handle simple situation where event listener methods execute a single statement involving an incoming event and a target object • Only provides a subset of what can be done with inner classes } • However, memory and disk footprint is smaller than for inner classes • Using EventHandler requires one class per listener type, using anonymous inner classes requires one class per 26 listener object java.beans.EventHandler • Has various static factory methods for creating proxy objects that implement a given listener interface package dotV2; import java.awt.*; import java.awt.event.*; import javax.swing.JPanel; import java.beans.EventHandler; public class Dot extends JPanel { private Point p; public Dot() { Dimension d = new Dimension(200, 200); . . . Object handler = EventHandler.create(MouseListener.class, this, "changePoint", "point", "mouseClicked"); • EventHandler objects are used behind the scenes to encapsulate info about the event, the target object, the method to call on the target and any argument to the method • java.lang.reflect.Proxy class implements listener methods; calls to listener methods are encoded and passed on to the EventHandler’s invoke method addMouseListener((MouseListener)handler); } . . . 27 java.beans.EventHandler • Intended to be used by builder tools—we will see how later • Removes the need for Beans to implement specific listener interfaces • Allows builder tools to connect arbitrary beans together • Weaker typing—specific listener interfaces implemented by a bean can be bypassed • Limited to transferring a single property from source event or bean to target bean 29 package actioneventsV2; . . . public class ActionSource2 extends JComboBox { public String getCurrentSelectedItemText() { return getSelectedItem().toString(); } public ActionSource2() { addItem("Item 1"); addItem("Item 2"); addItem("Item 3"); } } public class ActionReceiver extends JPanel { private JTextArea ta; public ActionReceiver() { ta = new JTextArea(10,20); add(ta); } public void acceptText(String text) { ta.append(text + "\n"); } 5 package mouseeventsV2; . . . public class MouseReceiver extends JPanel { private JTextArea ta; public MouseReceiver() { ta = new JTextArea(15, 40); JScrollPane js = new JScrollPane(ta); add(js); } Custom Events • Custom events are useful when one of your objects wants to notify another object about a change in its state • Six steps involved: • You must define a new class to describe the event (must extend EventObject) • You must define a new interface for listeners to receive this type of event (must extend EventListener) • The source must provide methods to allow listeners to register and deregister for event notifications • The source must provide code to generate the event and send it to all registered listeners • The listener must implement the interface to receive the event • The listener must register/deregister to receive the notifications public void mouseClicked() { ta.append("mouse clicked\n"); } public void mouseEntered() { ta.append("mouse entered\n"); } public void mouseExited() { ta.append("mouse exited\n"); } . . . Colour Event Example 32 package cselector; import java.util.*; public interface ColorListener extends EventListener { package cselector; import java.awt.*; import java.awt.event.*; import java.util.*; public class ColorEvent extends EventObject { private Color color; public ColorEvent(Object source, Color color) { super(source); this.color = color; } public Color getColor() { return color; } public void changeColor(ColorEvent ce); } package cselector; import java.awt.*; import javax.swing.JPanel; public class Painter extends JPanel implements ColorListener { private Color color; // constructor + paintComponent method omitted – see source . . . public void setColor(Color c) { color = c; repaint(); } public void changeColor(ColorEvent ce) { color = ce.getColor(); repaint(); } } } package cselector; import java.awt.*; import java.awt.event.*; import java.beans.*; import java.util.*; import javax.swing.JPanel; import javax.swing.JScrollBar; import javax.swing.JLabel; . . . public Color getColor() { return color; } public void fireColorEvent(ColorEvent ce) { Vector v; synchronized(this) { v = (Vector)listeners.clone(); } for(int i = 0; i < v.size(); i++) { ColorListener cl = (ColorListener)v.elementAt(i); cl.changeColor(ce); } } public class Selector extends JPanel implements AdjustmentListener { private Color color; private Vector listeners; private JScrollBar rScrollbar, gScrollbar, bScrollbar; // constructor, paintComponent & scrollbar handling code // omitted – see source for details } public void addColorListener(ColorListener cl) { listeners.addElement(cl); } public void removeColorListener(ColorListener cl) { listeners.removeElement(cl); } . . . 6 Reflection and Introspection • Reflection is the ability to obtain information about the fields, constructors and methods of a class at runtime • The typical Bean developer does not write code that uses reflection directly • However, it is useful to have some understanding of reflection because Introspection is based on it Reflection • Class • The Java Virtual Machine creates an instance of the class java.lang.Class for each type, including classes, interfaces, arrays, and simple types • Class provides various instance methods that allow you to get information about that type • Provides more than 30 different instance methods! See the javadocs 37 38 package reflect; public class IsInterfaceDemo { public static void main(String args[]) { try { // Get the class object Class c = Class.forName(args[0]); // Determine if it represents a class or interface if(c.isInterface()) { System.out.println(args[0] + " is an interface"); } else { System.out.println(args[0] + " is not an interface"); } } catch(Exception ex) { // the printStackTrace method is extremely useful for // debugging :-) ex.printStackTrace(); } Reflection • The java.lang.reflect package contains interfaces and classes that encapsulate information about constructors, methods, fields etc. • Eg. java.lang.reflect.Field contains methods that allow you to read and write the value of a field within another object (subject to Java language access control) } } 40 package reflect; import java.lang.reflect.*; public class GetFieldsDemo { public static void main(String args[]) { try { // Get the class object Class c = Class.forName(args[0]); // Display the fields Field fields[] = c.getFields(); for(int i = 0; i < fields.length; i++) { System.out.println(fields[i].getName()); } } catch(Exception ex) { ex.printStackTrace(); } } } Reflection • The class Method in java.lang.reflect alows you to get information about a method • Some methods in Method: Class [] getExceptionTypes() Class [] getParameterTypes() Class getReturnType() Object invoke(Object obj, Object [] args) Allows a builder tool to dynamically invoke a method of a Bean! This is exactly what is needed to customize a Bean by accessing its properties and to connect several Beans 42 7 // Generate parameters array Object parameters[] = new Double[nparameters]; for(int i = 0; i < nparameters; i++) { parameters[i] = new Double(args[i + 2]); } package reflect; import java.lang.reflect.*; // invoke a method in a class, where the class name, // method name, and any args are supplied on the // command line public class InvokeDemo { // Invoke method Object r; if(Modifier.isStatic(m.getModifiers())) { r = m.invoke(null, parameters); } else { r = m.invoke(c.newInstance(), parameters); } // Display results if (r != null) { System.out.println(r); } public static void main(String args[]) { try { // Get the class object Class c = Class.forName(args[0]); // Get reference to Method object int nparameters = args.length – 2; Class parameterTypes[] = new Class[nparameters]; for(int i = 0; i < nparameters; i++) { parameterTypes[i] = double.class; } Method m = c.getMethod(args[1], parameterTypes); } catch(Exception ex) { ex.printStackTrace(); } } } 8