Example

BakedBean.java see \Chapter2\1

import javax.swing.*; import javax.swing.event.*; import java.beans.*;

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("SansSerif", 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,3 0,3 0);

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 // ...an exception will be thrown here if there is a veto // ...if not, 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.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); frame.pack();

BakedBean has a visual representation (this is 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 orders 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 ChangeLis-teners. 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 it is executed as an application.

Figure 2.1

BakedBean in our custom JavaBeans property editor

Figure 2.1

BakedBean in our custom JavaBeans property editor

In chapter 18, section 18.9, we will 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 it 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). Any Swing component can be created, modified, serialized, and deserialized using this environment because every component is JavaBeans compliant.

Bean Container [Pioperties Table]

File E (Jit Layout

BakedBe-an

Editing BakedBean

HB

xl

Property

Value

background

204,204,204

a.

beancolor

150,0,0

beanFont

java awt.Font[family^Arial,name,.

ì

beanString

BakedBean #

1

beariValue

|l 999

border

null

É

Figure 2.2 BakedBean in our custom JavaBeans property editor

0 0

Post a comment

  • Receive news updates via email from this site