Easy to Learn Java: Programming Articles, Examples and Tips

Start with Java in a few days with Java Lessons or Lectures

Home

Code Examples

Java Tools

More Java Tools!

Java Forum

All Java Tips

Books

Submit News
Search the site here...
Search...
 

Chapter 2. (Introduction) Swing Mechanics. Easy for reading, Click here!

Chapter 2. (Introduction) Swing Mechanics. Easy for reading, Click here!

[ Return to Swing (Book) ]

Page: 7/14 


Previous Page Previous Page (6/14) - Next Page (8/14) Next Page
Subpages: 1. JComponent properties, size, and positioning 
2.  Event handling and dispatching 
3. Multithreading
4. Timers
5. AppContext service
6. Inside Timers & the TimerQueue
7. JavaBeans architecture
8. Fonts, Colors, Graphics and text
9. Using the Graphics clipping area
10. Graphics debugging
11. Painting and validation
12. Focus Management
13. Keyboard input, KeyStrokes, and Actions
14. SwingUtilities

2.7    JavaBeans architecture

Since we are concerned with creating Swing applications in this book, we need to understand and appreciate the fact that every component in Swing is a JavaBean.

Note: If you are familiar with the JavaBeans component model you may want to skip to the next section.

2.7.1    The JavaBeans component model

The JavaBeans specification identifies five features that each bean is expected to provide. We will review these features here, along with the classes and mechanisms that make them possible. The first thing to do is think of a simple component, such as a button, and apply what we discuss here to this component. Second, we are assuming basic knowledge of the Java Reflection API:

"Instances of Class represent classes and interfaces in a running Java application."API

"A Method provides information about, and access to, a single method on a class or interface."API

"A Field provides information about, and dynamic access to, a single field of a class or an interface."API

2.7.2    Introspection

Introspection is the ability to discover the methods, properties, and events information of a bean. This is accomplished through use of the java.beans.Introspector class. Introspector provides static methods to generate a BeanInfo object containing all discoverable information about a specific bean. This includes information from each of a bean's superclasses, unless we specify which superclass introspection should stop at (i.e. we can specify the 'depth' of an instrospection). The following retrieves all discoverable information of a bean:

    BeanInfo myJavaBeanInfo =

      Introspector.getBeanInfo(myJavaBean);

A BeanInfo object partitions all of a bean's information into several groups, some of which are:

         A BeanDescriptor: provides general descriptive information such as a display name.

         An array of EventSetDescriptors: provides information about a set of events a bean fires. These can be used to, among other things, retrieve that bean's event listener related methods as Method instances.

         An array of MethodDescriptors: provides information about the methods of a bean that are externally accessible (this would include, for instance, all public methods). This information is used to construct a Method instance for each method.

         An array of PropertyDescriptors: provides information about each property that a bean maintains which can be accessed through get, set, and/or is methods. These objects can be used to construct Method and Class instances corresponding to that property's accessor methods and class type respectively.

2.7.3    Properties

As we discussed in section 2.1.1, beans support different types of properties. Simple properties are variables such that, when modified, a bean will do nothing. Bound and constrained properties are variables such that, when modified, a bean will send notification events to any listeners. This notification takes the form of an event object which contains the property name, the old property value, and the new property value. Whenever a bound property changes, the bean should send out a PropertyChangeEvent. Whenever a constrained property is about to change, the bean should send out a PropertyChangeEvent before the change occurs, allowing it to possibly be vetoed. Other objects can listen for these events and process them accordingly (which leads to communication).

Associated with properties are a bean's setXX()/getXX() and isXX() methods. If a setXX() method is available the associated property is said to be writeable. If a getXX() or isXX() method is available the associated property is said to be readable. An isXX() method normally corresponds to retrieval of a boolean property (occasionaly getXX() methods are used for this as well).

2.7.4    Customization

A bean's properties are exposed through its setXX()/getXX() and isXX() methods, and can be modified at run-time (or design-time). JavaBeans are commonly used in interface development environments where property sheets can be displayed for each bean allowing read/write (depending on the available accessors) property functionality.

2.7.5    Communication

Beans are designed to send events that notify all event listeners registered with that bean, when a bound or constrained property changes value. Apps are constructed by registering listeners from bean to bean. Since we can use introspection to determine event sending and receiving information about any bean, design tools can take advantage of this knowledge to allow more powerful, design-time customization. Communication is the basic glue that holds an interactive GUI together.

2.7.6    Persistency

All JavaBeans must implement the Serializable interface (directly or indirectly) to allow serialization of their state into persistent storage (storage that exists beyond program termination). All objects are saved except those declared transient. (Note that JComponent directly implements this interface.)

Classes which need special processing during serialization need to implement the following private methods:

    private void writeObject(java.io.ObjectOutputStreamout) and

    private void readObject(java.io.ObjectInputStream in )

These methods are called to write or read an instance of this class to a stream. Note that the default serialization mechanism will be invoked to serialize all sub-classes because these are private methods. (Refer to the API documentation or Java tutorial for more information about serialization.)

Note: As of the first release of Java 2, JComponent implements readObject() and writeObject() as private. All subclasses need to implement these methods if special processing is desired. Currently long-term persistance is not recommended and is subject to change in future releases. However, there is nothing wrong with implementing Short-term persistance (e.g. for RMI, misc. data transfer, etc.).

Classes that intend to take comple control of their serialization and deserialization should, instead, implement the Externalizable interface.

Two methods are defined in the Externalizable interface:

    public void writeExternal(ObjectOutput out)

    public void readExternal(ObjectInput in)

These methods will be invoked when writeObject() and readObject() (discussed above) are invoked to handle any serialization/deserialization.

2.7.7    A simple Swing-based JavaBean

The following code demonstrates how to build a Swing-based JavaBean with simple, bound, constrained, and 'change' properties.

The code: BakedBean.java

see \Chapter1\1

import javax.swing.*;

import javax.swing.event.*;

import java.beans.*;

import java.awt.*;

import java.io.*;

public class BakedBean extends JComponent implements Externalizable

{

  // Property names (only needed for bound or constrained properties)

  public static final String BEAN_VALUE = "Value";

  public static final String BEAN_COLOR = "Color";

  // Properties

  private Font m_beanFont;           // simple

  private Dimension m_beanDimension; // simple

  private int m_beanValue;           // bound

  private Color m_beanColor;         // constrained

  private String m_beanString;       // change

  // Manages all PropertyChangeListeners

  protected SwingPropertyChangeSupport m_supporter =

    new SwingPropertyChangeSupport(this);

  // Manages all VetoableChangeListeners

  protected VetoableChangeSupport m_vetoer =

    new VetoableChangeSupport(this);

  // Only one ChangeEvent is needed since the event's only

  // state is the source property.  The source of events generated

  // is always "this". You'll see this in lots of Swing source.

  protected transient ChangeEvent m_changeEvent = null;

  // This can manage all types of listeners, as long as we set

  // up the fireXX methods to correctly look through this list.

  // This makes you appreciate the XXSupport classes.

  protected EventListenerList m_listenerList =

    new EventListenerList();

  public BakedBean() {

    m_beanFont = new Font("SanSerif", Font.BOLD | Font.ITALIC, 12);

    m_beanDimension = new Dimension(150,100);

    m_beanValue = 0;

    m_beanColor = Color.black;

    m_beanString = "BakedBean #";

  }

  public void paintComponent(Graphics g) {

    super.paintComponent(g);

    g.setColor(m_beanColor);

    g.setFont(m_beanFont);

    g.drawString(m_beanString + m_beanValue,30,30);

  }

  public void setBeanFont(Font font) {

    m_beanFont = font;

  }

  public Font getBeanFont() {

    return m_beanFont;

  }

  public void setBeanValue(int newValue) {

    int oldValue = m_beanValue;

    m_beanValue = newValue;

    // Notify all PropertyChangeListeners

    m_supporter.firePropertyChange(BEAN_VALUE,

      new Integer(oldValue), new Integer(newValue));

  }

  public int getBeanValue() {

    return m_beanValue;

  }

  public void setBeanColor(Color newColor)

   throws PropertyVetoException {

    Color oldColor = m_beanColor;

    // Notify all VetoableChangeListeners before making change

    // ...exception will be thrown here if there is a veto

    // ...if not we continue on and make the change

    m_vetoer.fireVetoableChange(BEAN_COLOR, oldColor, newColor);

    m_beanColor = newColor;

    m_supporter.firePropertyChange(BEAN_COLOR, oldColor, newColor);

  }

  public Color getBeanColor() {

    return m_beanColor;

  }

  public void setBeanString(String newString) {

    m_beanString = newString;

    // Notify all ChangeListeners

    fireStateChanged();

  }

  public String getBeanString() {

    return m_beanString;

  }

  public void setPreferredSize(Dimension dim) {

    m_beanDimension = dim;

  }

  public Dimension getPreferredSize() {

    return m_beanDimension;

  }

  public void setMinimumSize(Dimension dim) {

    m_beanDimension = dim;

  }

  public Dimension getMinimumSize() {

    return m_beanDimension;

  }

  public void addPropertyChangeListener(

   PropertyChangeListener l) {

    m_supporter.addPropertyChangeListener(l);

  }

  public void removePropertyChangeListener(

   PropertyChangeListener l) {

    m_supporter.removePropertyChangeListener(l);

  }

  public void addVetoableChangeListener(

   VetoableChangeListener l) {

    m_vetoer.addVetoableChangeListener(l);

  }

  public void removeVetoableChangeListener(

   VetoableChangeListener l) {

    m_vetoer.removeVetoableChangeListener(l);

  }

  // Remember that EventListenerList is an array of

  // key/value pairs:

  //   key = XXListener class reference

  //   value = XXListener instance

  public void addChangeListener(ChangeListener l) {

    m_listenerList.add(ChangeListener.class, l);

  }

  public void removeChangeListener(ChangeListener l) {

    m_listenerList.remove(ChangeListener.class, l);

  }

  // This is typical EventListenerList dispatching code.

  // You'll see this in lots of Swing source.

  protected void fireStateChanged() {

    Object[] listeners = m_listenerList.getListenerList();

    // Process the listeners last to first, notifying

    // those that are interested in this event

    for (int i = listeners.length-2; i>=0; i-=2) {

      if (listeners[i]==ChangeListener.class) {

       if (m_changeEvent == null)

         m_changeEvent = new ChangeEvent(this);

         ((ChangeListener)listeners[i+1]).stateChanged(m_changeEvent);

      }          

    }

  }

  public void writeExternal(ObjectOutput out) throws IOException {

    out.writeObject(m_beanFont);

    out.writeObject(m_beanDimension);

    out.writeInt(m_beanValue);

    out.writeObject(m_beanColor);

    out.writeObject(m_beanString);

  }

  public void readExternal(ObjectInput in)

   throws IOException, ClassNotFoundException {

    setBeanFont((Font)in.readObject());

    setPreferredSize((Dimension)in.readObject());

    // Use preferred size for minimum size..

    setMinimumSize(getPreferredSize());

    setBeanValue(in.readInt());

    try {

      setBeanColor((Color)in.readObject());

    }

    catch (PropertyVetoException pve) {

      System.out.println("Color change vetoed..");

    }

    setBeanString((String)in.readObject());

  }

  public static void main(String[] args) {

    JFrame frame = new JFrame("BakedBean");

    frame.getContentPane().add(new BakedBean());

    frame.setVisible(true);

    frame.pack();

  }

}

BakedBean has a visual representation (not a requirement for a bean). It has properties: m_beanValue, m_beanColor, m_beanFont, m_beanDimension, and m_beanString. It supports persistency by implementing the Externalizable interface and implementing the writeExternal() and readExternal() methods to control its own serialization (note that the order in which data is written and read match). BakedBean supports customization through its setXX() and getXX() methods, and it supports communication by allowing the registration of PropertyChangeListeners, VetoableChangeListeners, and ChangeListeners. And, without having to do anything special, it supports introspection.

Attaching a main method to display BakedBean in a frame does not get in the way of any JavaBeans functionality. Figure 2.1 shows BakedBean when executed as an application.

Figure 2.1 BakedBean in our custom JavaBeans property editor

<<file figure2-1.gif>>

In chapter 18 (section 18.9) we construct a full-featured JavaBeans property editing environment. Figure 2.2 shows a BakedBean instance in this environment. The BakedBean shown has had its m_beanDimension, m_beanColor, and m_beanValue properties modified with our property editor and was then serialized to disk. What figure 2.2 really shows is an instance of that BakedBean after it had been deserialized (loaded from disk). Note that any Swing component can be created, modified, serialized, and deserialized using this environment because they are all JavaBeans compliant!

Figure 2.2 BakedBean in our custom JavaBeans property editor

<<file figure2-2.gif>>



[ Return to Swing (Book) ]


Search Books
Custom Search
Latest articles
 SSL with GlassFish v2, page 5

 SSL with GlassFish v2, page 4

 SSL with GlassFish v2, page 3

 SSL with GlassFish v2, page 2

 The Java Lesson 2: Anatomy of a simple Java program, page 2

 New site about Java for robots and robotics: both software and hardware.

 Exceptions -III: What's an exception and why do I care?

 Exceptions -II: What's an exception and why do I care?

 Exceptions: What's an exception and why do I care?

 Double your Java code quality in 10 minutes, here is receipt

 Murach's Java Servlets and JSP

 How to get ascii code from a char in Java?

 Can we just try without catch? Yes!

 Make Tomcat page load faster

 Make your Tomcat More secure - limit network address for certain IP addresses

 New Java book online starts now here...

 Implementing RESTful Web Services in Java

 Firefox trimming from 1 GB to 40 Mb with many tabs opened

 SSL with GlassFish v2

 My request to replublish Tech Tips

 Search JavaFAQ.nu site here

 New Advanced Installer for Java 6.0 brings XML updates and imports 3rd party MSI

 EJB programming restrictions

 Maven vs Ant or Ant vs Maven?

 Why Java does not use default value which it should?

 How to unsign signed bytes in Java - your guide is here

 The Java Lesson 3: Identifiers and primitive data types. Page 2

 The Java Lesson 7: Bitwise operations with good examples, click here! Page 4

 The Java Lesson 7: Bitwise operations with good examples, click here! Page 3

 The Java Lesson 7: Bitwise operations with good examples, click here! Page 2


[ More in News Section ]


Home Code Examples Java Forum All Java Tips Books Submit News, Code... Search... Offshore Software Tech Doodling

RSS feed Java FAQ RSS feed Java FAQ News     

    RSS feed Java Forums RSS feed Java Forums

All logos and trademarks in this site are property of their respective owner. The comments are property of their posters, all the rest 1999-2006 by Java FAQs Daily Tips.

Interactive software released under GNU GPL, Code Credits, Privacy Policy