The following is a discussion about beans based upon the TextScrollBean example taken from Reaz Hoque's Programming JavaBeans 1.1 . We will build up to the full functionality of TextScrollBean in three stages. The first stage is represented by bean TextScrollBean1.java
Here is the source code for TextScrollBean1.java:
import java.awt.event.*; import java.awt.Graphics; import java.awt.*; import java.beans.*; public class TextScrollBean1 extends Panel implements java.io.Serializable, Runnable { String text = "Events, Properties, Introspection, Oh My!!!"; transient Thread kicker = null; int speed=10; int x = 0; int y = 30; int stringwidth; int width = 250; int height = 50; FontMetrics fm; // Offscreen graphics context and image to implement double buffering transient Image offscreen; transient Graphics goffscreen; // Declare and instantiate a PropertyChange object private PropertyChangeSupport changes = new PropertyChangeSupport(this); private VetoableChangeSupport vetos = new VetoableChangeSupport(this); public TextScrollBean1() { text = "Beans make components easy"; setFont(new Font("TimesRoman",Font.BOLD,36)); start(); } public Dimension getPreferredSize() { return (new Dimension(width, height)); } // Add a listener. This will get called by the BeanBox public void addPropertyChangeListener(PropertyChangeListener l) { changes.addPropertyChangeListener(l); } // Remove a listener. This will get called by the BeanBox public void removePropertyChangeListener(PropertyChangeListener l) { changes.removePropertyChangeListener(l); } // Add a veto listener. This will get called by the BeanBox public void addVetoableChangeListener(VetoableChangeListener l) { vetos.addVetoableChangeListener(l); } // Remove a veto listener. This will get called by the BeanBox public void removeVetoableChangeListener(VetoableChangeListener l) { vetos.removeVetoableChangeListener(l); } // This method can be used to connect a Button to the // TextScrollBean.startScrolling method public void startScrolling(ActionEvent ex) { kicker.resume(); } // This method can be used to connect a Button to the // TextScrollBean.stopScrolling method public void stopScrolling(ActionEvent ex) { kicker.suspend(); } public void start() { if(kicker == null) { kicker = new Thread(this); kicker.start(); } } public void stop() { kicker = null; } public void run() { while (kicker != null) { try { Thread.sleep(speed); } catch (InterruptedException e) { e.printStackTrace(); } repaint(); } kicker = null; } public void paint(Graphics g) { update(g); } public void update(Graphics g) { fm = g.getFontMetrics(); stringwidth = fm.stringWidth(text); // Added double buffering to eliminate flashing // Create an offscreen graphics context if (goffscreen == null) { offscreen = createImage(width,height); goffscreen = offscreen.getGraphics(); } // Paint to our offscreeen graphics context goffscreen.setColor(getBackground()); goffscreen.fillRect(0,0,width,height); goffscreen.setColor(getForeground()); goffscreen.drawString(text, x, y); // Paint our offscreen image to the screen g.drawImage(offscreen,0,0,this); if (x <= (-stringwidth)) { x=width; } else { x--; } } } |
The important thing to notice is that it extends Panel and necessarily will have all the properties of Panel once made into a bean. The TextScrollBean1.java adds functionality to act as a source for PropertyChangeEvent events to listeners (other beans) its bound or constrained properties. Bound property changes are conveyed to PropertyChangeListener's. Constrained property changes are conveyed to VetoableChangeListener's. TextScrollBean1.java can handle both.
You should be able to package TextScrollBean1 into a bean. On the next page we will add a bit more to
TextScrollBeans1 and rename it as TextScrollBean2. But first, look at the properties of TextScrollBean1
in the beanbox. Notice how similar it is to Panel.