Properties, Methods, and Events

   

Java™ 2 Primer Plus
By Steven Haines, Steve Potts

Table of Contents
Chapter 15.  JavaBeans


A JavaBean that only contains properties is a poor excuse for a component. The JavaBeans specification states that the three most important features of a JavaBean are the set of properties it exposes, the set of methods it allows other components to call, and the set of events it fires. We have already seen how to get and set simple properties. Next, we will focus on ways to take advantage of the methods and events that a JavaBean can define.

Creating New Methods

The getter and setter methods enable you to get and set the properties of the JavaBean. It is possible to define methods that perform other tasks, however. Listing 15.4 shows a class that contains a method that is neither a get nor a set:

Listing 15.4 The GreenBean Class
 /*   * GreenBean.java   *   * Created on August 28, 2002, 10:41 AM   */  package com.samspublishing.jpp.ch15;  import java.io.Serializable;  import java.awt.*;  import java.beans.*;  /**   *   * @author  Stephen Potts   * @version   */  public class GreenBean extends Canvas implements Serializable  {       private Color color = Color.green;      public Color getColor()      {          return color;      }      public void setColor(Color col)      {          this.color = col;      }      /** Creates new GreenBean */      public GreenBean()      {          setSize(60,40);          setBackground(Color.green);      }      public void paint (Graphics g)      {          g.setColor(color);           g.fillRect(20,5,20,30);      }      public void printoutChange(PropertyChangeEvent evt)      {          String changeText = evt.getPropertyName() + " := "                  + evt.getNewValue();          System.out.println(changeText);      }  }//class 

In addition to the usual methods such as paint(), getColor(), and setColor(), this Bean contains an additional method called printoutChange(). This method accepts a PropertyChangeEvent object as input. It examines the event object and obtains the information that it contains. It then prints this information to the console:

 String changeText = evt.getPropertyName() + " := "          + evt.getNewValue();  System.out.println(changeText); 

This method is public, meaning that it can be called from other classes. Both the getXXX() and setXXX() methods are called whenever the user changes the property's value using the GUI. With custom methods, however, you have to provide explicit calls to this method from the other classes.

We will wait to build and deploy the GreenBean class until we have created one additional class, ButtonBean, in the following section.

Events

Another important part of the JavaBean specification is the ability to define your own custom events. The two basic categories of events are standard and custom. A standard event is one that is generated by one of the classes that compose the JDK. These events can be low-level, such as mouse events, or they can be high-level, or semantic, such as ActionEvent. Custom events are those that you can create yourself by extending either the EventObject class or the AWTEvent class. In the next section, you will see how one very interesting type of event, the PropertyChangeEvent, is communicated between JavaBeans.

The PropertyChangeEvent

The getXXX() and setXXX() methods provide ways for development tools such as Forte to manipulate the Beans in their user interfaces. There are two special types of properties: bound properties and constrained properties.

A Bound property is a property that has the built-in functionality to notify another JavaBean when it changes. One good use of this feature is to manage appearance properties like the font property. If a container Bean held six Beans with text on them, it would be nice to be able to change the font on all six of them by changing the font of the container. You could do this by binding a method in each Bean to the font property of the container.

A Constrained Property goes even further. In addition to notifying the other Beans when a property changes, the Bean that is being notified can veto the change. This could be useful if a container Bean wanted to maintain a consistent font in all the contained Beans. If any Bean wanted to change its font, the container Bean could veto it.

An example that makes use of the printoutChange() method that we created in the GreenBean class can be used to show how this works. Recall that GreenBean contains a method called printoutChange() that accepts a PropertyChangeEvent as its parameter:

 public void printoutChange(PropertyChangeEvent evt)  {      String changeText = evt.getPropertyName() + " := "              + evt.getNewValue();      System.out.println(changeText);  } 

This method will be called automatically when this event occurs once the event listener is defined. It will accept the Event, get the values in its variables that pertain to the name of the property that was changed, and then get the new value of the property.

When this method gets called, the information contained in the Event object will be printed to the console. JavaBeans that contain bound properties must be written in a special way so that PropertyChangeEvents can be sent whenever a bound property changes. Listing 15.5 shows a Bean that is capable of sending PropertyChangedEvents:

Listing 15.5 The ButtonBean Class
 /*   * ButtonBean.java   *   * Created on August 28, 2002, 11:38 AM   */  package com.samspublishing.jpp.ch15;  import java.awt.*;  import java.awt.event.*;  import java.beans.*;  import java.io.Serializable;  import java.util.Vector;  /**   *   * @author  Stephen Potts   * @version   */  public class ButtonBean extends Component implements Serializable  {      private boolean debug;      private PropertyChangeSupport pcs=         new PropertyChangeSupport(this);       private String label;      /** Creates new ButtonBean */      public ButtonBean()      {          this("ButtonBean");      }      public ButtonBean(String label)      {          super();          this.label = label;          setFont(new Font("Dialog", Font.PLAIN, 12));          setBackground(Color.lightGray);      }      public synchronized void paint(Graphics g)      {          int width = getSize().width;          int height = getSize().height;          g.setColor(getBackground());          g.fill3DRect(0, 0, width-1, height-1, false);           g.setColor(getForeground());          g.setFont(getFont());          g.drawRect(2, 2, width-4, height-4);           g.drawString(label, 10, 18);      }      public void addPropertyChangeListener(PropertyChangeListener pcl)      {          pcs.addPropertyChangeListener(pcl);      }      public void removePropertyChangeListener(PropertyChangeListener pcl)      {          pcs.addPropertyChangeListener(pcl);      }      public void setDebug(boolean x)       {          boolean old = debug;          debug = x;          pcs.firePropertyChange("debug", new Boolean(old),          new Boolean(x));      }      public boolean getDebug()      {          return debug;      }      public void setFontSize(int x)      {          Font old = getFont();          setFont(new Font(old.getName(), old.getStyle(), x));          pcs.firePropertyChange("fontSize",          new Integer(old.getSize()), new Integer(x));      }      public int getFontSize()      {          return getFont().getSize();      }      public void setFont(Font f)      {          Font old = getFont();          super.setFont(f);          pcs.firePropertyChange("font", old, f);      }      public void setLabel(String lab)      {          String oldLabel = label;          label = lab;          pcs.firePropertyChange("label", oldLabel, lab);      }       public String getLabel()      {          return label;      }      public Dimension getPreferredSize()      {          FontMetrics fm = getFontMetrics(getFont());          return new Dimension(fm.stringWidth(label) + 12,          fm.getMaxAscent() + fm.getMaxDescent() + 8);      }      public void setForeground(Color c)      {          Color old = getForeground();;          super.setForeground(c);          pcs.firePropertyChange("foreground", old, c);          repaint();      }      public void setBackground(Color c)      {          Color old = getBackground();;          super.setBackground(c);          pcs.firePropertyChange("background", old, c);          repaint();      }  }//class 

The PropertyChangeEvent is part of the JavaBeans package:

 import java.beans.*; 

The PropertyChangeSupport is a utility class for bound properties. It will be used to hold the list of classes that are listening for this class' PropertyChangeEvents.

 private PropertyChangeSupport pcs=     new PropertyChangeSupport(this); 

The following two methods allow other Beans to register and remove their interest in being notified of changes to bound properties:

 public void addPropertyChangeListener(PropertyChangeListener pcl)  {      pcs.addPropertyChangeListener(pcl);  }  public void removePropertyChangeListener(PropertyChangeListener pcl)  {      pcs.addPropertyChangeListener(pcl);  } 

Notice that all the set methods for the bound properties have to include an additional line of code to fire the property change event by calling the firePropertyChange() method. The firePropertyChange() method takes three parameters: the name of the property to be changed, the old value being sent, and the new value.

 public void setFontSize(int x)      {          Font old = getFont();          setFont(new Font(old.getName(), old.getStyle(), x));          pcs.firePropertyChange("fontSize",          new Integer(old.getSize()), new Integer(x));      } 

Caution

graphics/01icon17.gif

All the parameters in the firePropertyChange() method are sent as objects. Intrinsic types, such as int, must be sent using the object version like Integer.


The only task that remains is the connecting of the two Beans together. This is normally done using the development tool's user interface. In this case, we will use the BeanBox application.

The process for adding these Beans to the BeanBox is identical to the procedure described in the "Deploying JavaBeans" section earlier in this chapter.

  1. Create a directory called c:\com\samspublishing\jpp\ch15.

  2. Copy the following files from the Sams Web site to this directory:

    GreenBean.java

    ButtonBean.java

  3. Compile the two .java files.

  4. Create a file called GreenBean.mf in this directory that contains the following lines:

     Manifest-Version: 1.0  Created-By: 1.4.0 (Sun Microsystems Inc.)  Name: com/samspublishing/jpp/ch15/GreenBean.class  Java-Bean: True 

  5. Create a file called ButtonBean.mf in this directory that contains the following lines:

     Manifest-Version: 1.0  Created-By: 1.4.0 (Sun Microsystems Inc.)  Name: com/samspublishing/jpp/ch15/ButtonBean.class  Java-Bean: True 

  6. cd up to c:\.

  7. Type the following command:

     jar cfm com\samspublishing\jpp\ch15\ButtonBean.jar com\samspublishing\jpp\ch15\ButtonBean.mf com\samspublishing\jpp\ch15\ButtonBean.class 

  8. Type the following command:

    [View full width]

    jar cfm com\samspublishing\jpp\ch15\GreenBean.jar com\samspublishing\jpp\ch15\GreenBean.mf graphics/ccc.gif com\samspublishing\jpp\ch15\GreenBean.class

  9. Look in c:\com\samspublishing\jpp\ch15 and see that two files named ButtonBean.jar and GreenBean.jar exist. Open them with a zip program and verify that they contain one class file and one manifest file.

  10. Copy the ButtonBean.jar and GreenBean.jar files into the C:\BDK\jars directory.

Next, start the BeanBox and place one instance of ButtonBean in the BeanBox along with one instance of GreenBean. Following that, highlight the ButtonBean instance, then, choose Events from the Edit menu, then propertyChange, then propertyChange again as shown in Figure 15.11.

Figure 15.11. The GreenBean listens for changes to the ButtonBean's properties and prints them to the console.

graphics/15fig11.gif

A red line will be attached to your mouse cursor. Move your mouse cursor over the GreenBean and click. This signifies that you want the GreenBean to listen to the bound property changes generated by the ButtonBean. After clicking you will see a dialog box appear as shown in Figure 15.12.

Figure 15.12. The printoutChanges method is the GreenBean method that handles bound changes.

graphics/15fig12.gif

You will see quite a few methods that are inherited from GreenBean's superclasses. You will also see the printoutChange() method. Choose this one. Make the BeanBox console visible and change the properties of the ButtonBean using the BeanBox's Properties window. You will see output for every change you make appear on the console, similar to what is shown here:

 debug := true  font := java.awt.Font[family=dialog.italic,name=Dialog,style=italic,size=12]  font := java.awt.Font[family=dialog.italic,name=Dialog,style=italic,size=14]  foreground := java.awt.Color[r=255,g=175,b=175]  label := Java Primer Plus 

One interesting modification that you can make to this example is to remove the println() statements in the printoutChange() method and replace them with methods that perform some task on your system, such as a database access.


       
    Top
     



    Java 2 Primer Plus
    Java 2 Primer Plus
    ISBN: 0672324156
    EAN: 2147483647
    Year: 2001
    Pages: 332

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