Here is the source code for TextScrollBean2.java:
import java.awt.event.*; import java.awt.Graphics; import java.awt.*; import java.beans.*; public class TextScrollBean2 extends Panel implements java.io.Serializable, Runnable { String text = null; 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 TextScrollBean2() { text = "Beans make components easy"; setFont(new Font("TimesRoman",Font.BOLD,36)); start(); } public Dimension getPreferredSize() { return (new Dimension(width, height)); } public String getTextString() { return text; } public void setTextString(String newtext) { text = newtext; } public int getSpeed() { return speed; } public void setSpeed(int newSpeed) throws PropertyVetoException { // tell vetoers about the change vetos.fireVetoableChange("Speed", "" + speed, "" + newSpeed); // Send change event to listeners when // speed is changed changes.firePropertyChange("Speed", "" + speed, "" + newSpeed); speed = newSpeed; } // 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--; } } } |
In addition to what TextScrollBean1 does to act as a source of design-time events, TextScrollBean2 adds two properties: speed and text. Notice the fields, setter methods, and getter methods.
You should be able to package TextScrollBean2 into a bean. On the next page we will add a bit more to
TextScrollBeans2 and rename it as TextScrollBean - Hoque's full blown bean example. But first, look
at the properties of TextScrollBean2 in the beanbox. Notice the two properties in addition to
those of Panel and TextScrollBean1.