Java/Swing JFC/Customized Component
Содержание
Alias Bean
<source lang="java">
/*
* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002. All rights * reserved. Software written by Ian F. Darwin and others. $Id: LICENSE,v 1.8 * 2004/02/09 03:33:38 ian Exp $ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. 2. Redistributions in * binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other * materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS"" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee cup" * logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s, * pioneering role in inventing and promulgating (and standardizing) the Java * language and environment is gratefully acknowledged. * * The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for * inventing predecessor languages C and C++ is also gratefully acknowledged. */
import java.awt.BorderLayout; import java.awt.Container; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.Vector; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; class AliasBean extends JPanel {
protected Vector aliVector; protected JList aliJList; private JTextField nameTF, addrTF; public AliasBean() { aliVector = new Vector(); aliJList = new JList(); // XXX MUST FIX THIS // aliJList.setSelectionMode(JList.SINGLE_SELECTION); aliJList.addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent evt) { int i = aliJList.getSelectedIndex(); if (i < 0) return; Alias al = (Alias) aliVector.get(i); nameTF.setText(al.getName()); addrTF.setText(al.getAddress()); } }); setLayout(new BorderLayout()); add(BorderLayout.WEST, new JScrollPane(aliJList)); JPanel rightPanel = new JPanel(); add(BorderLayout.EAST, rightPanel); rightPanel.setLayout(new GridLayout(0, 1)); JPanel buttons = new JPanel(); rightPanel.add(buttons); buttons.setLayout(new GridLayout(0, 1, 15, 15)); JButton b; buttons.add(b = new JButton("Set")); b.setToolTipText("Add or Change an alias"); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { int i = aliJList.getSelectedIndex(); if (i < 0) { // XXX error dialog?? return; } setAlias(i, nameTF.getText(), addrTF.getText()); } }); buttons.add(b = new JButton("Delete")); b.setToolTipText("Delete the selected alias"); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { int i = aliJList.getSelectedIndex(); if (i < 0) { return; } deleteAlias(i); } }); buttons.add(b = new JButton("Apply")); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { System.err.println("NOT WRITTEN YET"); } }); JPanel fields = new JPanel(); rightPanel.add(fields); fields.setLayout(new GridLayout(2, 2)); fields.add(new JLabel("Name")); fields.add(nameTF = new JTextField(10)); fields.add(new JLabel("Address")); fields.add(addrTF = new JTextField(20)); } public String expandAlias(String ali) { Alias a = findAlias(ali); if (a == null) return null; return a.getAddress(); } public Alias findAlias(String ali) { for (int i = 0; i < aliVector.size(); i++) { Alias a = (Alias) aliVector.get(i); if (a.getName().equals(ali)) return a; } return null; // not found } /** Add an Alias */ public void addAlias(Alias a) { Alias al = findAlias(a.getName()); if (al == null) { aliVector.addElement(a); } else { // aliVector.setElement(a); // XXX fuzzy } aliJList.setListData(aliVector); } /** Add an alias, by its constituent parts */ public void addAlias(String nn, String addr) { addAlias(new Alias(nn, addr)); } /** Replace an Alias */ public void setAlias(int n, String nam, String addr) { // TODO find it, replace it, or add it. aliVector.setElementAt(new Alias(nam, addr), n); aliJList.setListData(aliVector); } public void deleteAlias(int i) { aliVector.removeElementAt(i); aliJList.setListData(aliVector); }
} class Alias {
/** The name for the alias */ protected String name; /** The email address for this alias */ protected String address; public Alias(String n, String addr) { name = n; address = addr; } public String toString() { return name + " = " + address; } /** Get name */ public String getName() { return name; } /** Set name */ public void setName(String name) { this.name = name; } /** Get address */ public String getAddress() { return address; } /** Set address */ public void setAddress(String address) { this.address = address; }
} /**
* Test for AliasBean. * * @version $Id: AliasBeanTest.java,v 1.3 2004/02/09 03:33:48 ian Exp $ */
public class AliasBeanTest extends JFrame {
JButton quitButton; /** "main program" method - construct and show */ public static void main(String[] av) { // create a JFrameDemo object, tell it to show up new AliasBeanTest().setVisible(true); } /** Construct the object including its GUI */ public AliasBeanTest() { super("AliasBeanTest"); Container cp = getContentPane(); AliasBean ab = new AliasBean(); cp.add(BorderLayout.CENTER, ab); ab.addAlias("ian-cvs", "ian@openbsd.org"); ab.addAlias("ian-dos", "http://www.darwinsys.ru/"); cp.add(BorderLayout.SOUTH, quitButton = new JButton("Exit")); quitButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { setVisible(false); dispose(); System.exit(0); } }); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { setVisible(false); dispose(); System.exit(0); } }); pack(); }
}
</source>
Customized component
<source lang="java">
import java.awt.Color; import java.awt.Dimension; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.beans.Customizer; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.util.Calendar; import java.util.Date; import javax.swing.JButton; import javax.swing.JFrame; public class Clock extends JButton implements Customizer, Externalizable,
Runnable { protected PropertyChangeSupport propertyChangeSupport; protected boolean isDigital = false; protected Calendar calendar = Calendar.getInstance(); public Clock() { propertyChangeSupport = new PropertyChangeSupport(this); setBackground(Color.white); setForeground(Color.black); (new Thread(this)).start(); } public void writeExternal(ObjectOutput out) throws IOException { out.writeBoolean(isDigital); out.writeObject(getBackground()); out.writeObject(getForeground()); out.writeObject(getPreferredSize()); } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { setDigital(in.readBoolean()); setBackground((Color) in.readObject()); setForeground((Color) in.readObject()); setPreferredSize((Dimension) in.readObject()); } public Dimension getPreferredSize() { return new Dimension(50, 50); } public Dimension getMinimumSize() { return getPreferredSize(); } public Dimension getMaximumSize() { return getPreferredSize(); } public void setDigital(boolean digital) { propertyChangeSupport.firePropertyChange("digital", new Boolean( isDigital), new Boolean(digital)); isDigital = digital; repaint(); } public boolean getDigital() { return isDigital; } public void addPropertyChangeListener(PropertyChangeListener lst) { if (propertyChangeSupport != null) propertyChangeSupport.addPropertyChangeListener(lst); } public void removePropertyChangeListener(PropertyChangeListener lst) { if (propertyChangeSupport != null) propertyChangeSupport.removePropertyChangeListener(lst); } public void setObject(Object bean) { } public void paintComponent(Graphics g) { super.paintComponent(g); Color colorRetainer = g.getColor(); g.setColor(getBackground()); g.fillRect(0, 0, getWidth(), getHeight()); getBorder().paintBorder(this, g, 0, 0, getWidth(), getHeight()); calendar.setTime(new Date()); // get current time int hrs = calendar.get(Calendar.HOUR_OF_DAY); int min = calendar.get(Calendar.MINUTE); g.setColor(getForeground()); if (isDigital) { String time = "" + hrs + ":" + min; g.setFont(getFont()); FontMetrics fm = g.getFontMetrics(); int y = (getHeight() + fm.getAscent()) / 2; int x = (getWidth() - fm.stringWidth(time)) / 2; g.drawString(time, x, y); } else { int x = getWidth() / 2; int y = getHeight() / 2; int rh = getHeight() / 4; int rm = getHeight() / 3; double ah = ((double) hrs + min / 60.0) / 6.0 * Math.PI; double am = min / 30.0 * Math.PI; g.drawLine(x, y, (int) (x + rh * Math.sin(ah)), (int) (y - rh * Math.cos(ah))); g.drawLine(x, y, (int) (x + rm * Math.sin(am)), (int) (y - rm * Math.cos(am))); } g.setColor(colorRetainer); } public void run() { while (true) { repaint(); try { Thread.sleep(30 * 1000); } catch (InterruptedException ex) { break; } } } public static void main(String[] a) { JFrame f = new JFrame(); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); Clock c = new Clock(); f.getContentPane().add("Center", c); f.pack(); f.setSize(new Dimension(300, 300)); f.show(); }
}
</source>
Demonstrating the Box Component
<source lang="java">
import java.awt.Color; import java.awt.Container; import java.awt.Graphics; import java.awt.GridLayout; import java.awt.Insets; import java.awt.Polygon; import javax.swing.BorderFactory; import javax.swing.JComponent; import javax.swing.JFrame; public class RedBlueBox extends JComponent {
public void paintComponent(Graphics g) { Insets insets = getInsets(); int endX = getWidth() - insets.right; int endY = getHeight() - insets.bottom; // get the top-left corner int x = insets.left; int y = insets.top; g.setColor(Color.RED); Polygon p = new Polygon(); p.addPoint(x, y); p.addPoint(endX, y); p.addPoint(x, endY); g.fillPolygon(p); g.setColor(Color.BLUE); p.reset(); p.addPoint(endX, y); p.addPoint(x, endY); p.addPoint(endX, endY); g.fillPolygon(p); } public static void main(String args[]) { JFrame frame = new JFrame(); Container contentPane = frame.getContentPane(); contentPane.setLayout(new GridLayout(0, 1)); JComponent comp = new RedBlueBox(); comp.setBorder(BorderFactory.createMatteBorder(5, 5, 5, 5, Color.PINK)); contentPane.add(comp); comp = new RedBlueBox(); contentPane.add(comp); frame.setSize(300, 200); frame.show(); }
}
</source>
FontChooser dialog
<source lang="java">
/* Java Swing, 2nd Edition By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole ISBN: 0-596-00408-7 Publisher: O"Reilly
- /
// FontPicker.java //A quick test of the FontChooser dialog. (see FontChooser.java) // import java.awt.BorderLayout; import java.awt.Color; import java.awt.Container; import java.awt.Dimension; import java.awt.Font; import java.awt.Frame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JColorChooser; import javax.swing.JComboBox; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.SwingConstants; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.text.AttributeSet; import javax.swing.text.SimpleAttributeSet; import javax.swing.text.StyleConstants; public class FontPicker extends JFrame {
Color c; public FontPicker() { super("JColorChooser Test Frame"); setSize(200, 100); final JButton go = new JButton("Show FontChooser"); go.addActionListener(new ActionListener() { final FontChooser chooser = new FontChooser(FontPicker.this); boolean first = true; public void actionPerformed(ActionEvent e) { chooser.setVisible(true); // If we got a real font choice, then update our go button if (chooser.getNewFont() != null) { go.setFont(chooser.getNewFont()); go.setForeground(chooser.getNewColor()); } } }); getContentPane().add(go); setDefaultCloseOperation(EXIT_ON_CLOSE); } public static void main(String args[]) { FontPicker fp = new FontPicker(); fp.setVisible(true); }
} //FontChooser.java //A font chooser that allows users to pick a font by name, size, style, and //color. The color selection is provided by a JColorChooser pane. This //dialog builds an AttributeSet suitable for use with JTextPane. // class FontChooser extends JDialog implements ActionListener {
JColorChooser colorChooser; JComboBox fontName; JCheckBox fontBold, fontItalic; JTextField fontSize; JLabel previewLabel; SimpleAttributeSet attributes; Font newFont; Color newColor; public FontChooser(Frame parent) { super(parent, "Font Chooser", true); setSize(450, 450); attributes = new SimpleAttributeSet(); // Make sure that any way the user cancels the window does the right // thing addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { closeAndCancel(); } }); // Start the long process of setting up our interface Container c = getContentPane(); JPanel fontPanel = new JPanel(); fontName = new JComboBox(new String[] { "TimesRoman", "Helvetica", "Courier" }); fontName.setSelectedIndex(1); fontName.addActionListener(this); fontSize = new JTextField("12", 4); fontSize.setHorizontalAlignment(SwingConstants.RIGHT); fontSize.addActionListener(this); fontBold = new JCheckBox("Bold"); fontBold.setSelected(true); fontBold.addActionListener(this); fontItalic = new JCheckBox("Italic"); fontItalic.addActionListener(this); fontPanel.add(fontName); fontPanel.add(new JLabel(" Size: ")); fontPanel.add(fontSize); fontPanel.add(fontBold); fontPanel.add(fontItalic); c.add(fontPanel, BorderLayout.NORTH); // Set up the color chooser panel and attach a change listener so that // color // updates get reflected in our preview label. colorChooser = new JColorChooser(Color.black); colorChooser.getSelectionModel().addChangeListener( new ChangeListener() { public void stateChanged(ChangeEvent e) { updatePreviewColor(); } }); c.add(colorChooser, BorderLayout.CENTER); JPanel previewPanel = new JPanel(new BorderLayout()); previewLabel = new JLabel("Here"s a sample of this font."); previewLabel.setForeground(colorChooser.getColor()); previewPanel.add(previewLabel, BorderLayout.CENTER); // Add in the Ok and Cancel buttons for our dialog box JButton okButton = new JButton("Ok"); okButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { closeAndSave(); } }); JButton cancelButton = new JButton("Cancel"); cancelButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { closeAndCancel(); } }); JPanel controlPanel = new JPanel(); controlPanel.add(okButton); controlPanel.add(cancelButton); previewPanel.add(controlPanel, BorderLayout.SOUTH); // Give the preview label room to grow. previewPanel.setMinimumSize(new Dimension(100, 100)); previewPanel.setPreferredSize(new Dimension(100, 100)); c.add(previewPanel, BorderLayout.SOUTH); } // Ok, something in the font changed, so figure that out and make a // new font for the preview label public void actionPerformed(ActionEvent ae) { // Check the name of the font if (!StyleConstants.getFontFamily(attributes).equals( fontName.getSelectedItem())) { StyleConstants.setFontFamily(attributes, (String) fontName .getSelectedItem()); } // Check the font size (no error checking yet) if (StyleConstants.getFontSize(attributes) != Integer.parseInt(fontSize .getText())) { StyleConstants.setFontSize(attributes, Integer.parseInt(fontSize .getText())); } // Check to see if the font should be bold if (StyleConstants.isBold(attributes) != fontBold.isSelected()) { StyleConstants.setBold(attributes, fontBold.isSelected()); } // Check to see if the font should be italic if (StyleConstants.isItalic(attributes) != fontItalic.isSelected()) { StyleConstants.setItalic(attributes, fontItalic.isSelected()); } // and update our preview label updatePreviewFont(); } // Get the appropriate font from our attributes object and update // the preview label protected void updatePreviewFont() { String name = StyleConstants.getFontFamily(attributes); boolean bold = StyleConstants.isBold(attributes); boolean ital = StyleConstants.isItalic(attributes); int size = StyleConstants.getFontSize(attributes); //Bold and italic don"t work properly in beta 4. Font f = new Font(name, (bold ? Font.BOLD : 0) + (ital ? Font.ITALIC : 0), size); previewLabel.setFont(f); } // Get the appropriate color from our chooser and update previewLabel protected void updatePreviewColor() { previewLabel.setForeground(colorChooser.getColor()); // Manually force the label to repaint previewLabel.repaint(); } public Font getNewFont() { return newFont; } public Color getNewColor() { return newColor; } public AttributeSet getAttributes() { return attributes; } public void closeAndSave() { // Save font & color information newFont = previewLabel.getFont(); newColor = previewLabel.getForeground(); // Close the window setVisible(false); } public void closeAndCancel() { // Erase any font information and then close the window newFont = null; newColor = null; setVisible(false); }
}
</source>
Oval Panel
<source lang="java">
import java.awt.Color; import java.awt.Container; import java.awt.Graphics; import java.awt.GridLayout; import javax.swing.JFrame; import javax.swing.JPanel; public class OvalPanel extends JPanel {
Color color; public OvalPanel() { this(Color.black); } public OvalPanel(Color color) { this.color = color; } public void paintComponent(Graphics g) { int width = getWidth(); int height = getHeight(); g.setColor(color); g.drawOval(0, 0, width, height); } public static void main(String args[]) { JFrame frame = new JFrame("Oval Sample"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Container content = frame.getContentPane(); content.setLayout(new GridLayout(2, 2)); Color colors[] = { Color.red, Color.blue, Color.green, Color.yellow }; for (int i = 0; i < 4; i++) { OvalPanel panel = new OvalPanel(colors[i]); content.add(panel); } frame.setSize(300, 200); frame.setVisible(true); }
}
</source>
Ploygon Button
<source lang="java">
import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Polygon; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionAdapter; import java.awt.event.MouseMotionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import javax.swing.JApplet; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JToolTip; import javax.swing.Timer; public class PolygonButton extends JComponent implements MouseListener,
MouseMotionListener { static public Color ACTIVE_COLOR = Color.red; static public Color INACTIVE_COLOR = Color.darkGray; protected String text; protected Polygon polygon; protected Rectangle rectangle; protected boolean isActive; protected static PolygonButton button; public PolygonButton(Polygon p, String text) { polygon = p; setText(text); setOpaque(false); addMouseListener(this); addMouseMotionListener(this); rectangle = new Rectangle(polygon.getBounds()); // Bug alert! rectangle.grow(1, 1); setBounds(rectangle); polygon.translate(-rectangle.x, -rectangle.y); } public void setText(String t) { text = t; } public String getText() { return text; } public void mouseMoved(MouseEvent e) { if (!rectangle.contains(e.getX(), e.getY()) || e.isConsumed()) { if (isActive) { isActive = false; repaint(); } return; // quickly return, if outside our rectangle } int x = e.getX() - rectangle.x; int y = e.getY() - rectangle.y; boolean active = polygon.contains(x, y); if (isActive != active) setState(active); if (active) e.consume(); } public void mouseDragged(MouseEvent e) { } protected void setState(boolean active) { isActive = active; repaint(); if (active) { if (button != null) button.setState(false); setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); } else { button = null; setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } } public void mouseClicked(MouseEvent e) { } public void mousePressed(MouseEvent e) { } public void mouseReleased(MouseEvent e) { } public void mouseExited(MouseEvent e) { mouseMoved(e); } public void mouseEntered(MouseEvent e) { mouseMoved(e); } public void paint(Graphics g) { g.setColor(isActive ? ACTIVE_COLOR : INACTIVE_COLOR); g.drawPolygon(polygon); } public static void main(String[] argv) { JFrame f = new JFrame(); f.setSize(400, 300); Polygon p = new Polygon(); p.addPoint(10, 10); p.addPoint(100, 300); p.addPoint(300, 300); p.addPoint(10, 10); PolygonButton btn = new PolygonButton(p, "button"); f.getContentPane().add(btn); WindowListener wndCloser = new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }; f.addWindowListener(wndCloser); f.setVisible(true); }
}
</source>
The MyBean JavaBean Component
<source lang="java">
import java.awt.Point; import java.beans.XMLEncoder; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; public class MyBean {
private String names[]; private Point p; private int length; public String[] getNames() { return names; } public Point getPoint() { return p; } public int getLength() { return length; } public void setNames(String newValue[]) { names = newValue; } public void setPoint(Point newValue) { p = newValue; } public void setLength(int newValue) { length = newValue; } public static void main(String args[]) throws IOException { // Create MyBean saveme = new MyBean(); saveme.setNames(new String[] { "one", "two", "three" }); saveme.setPoint(new Point(15, 27)); saveme.setLength(6); // Save XMLEncoder encoder = new XMLEncoder(new BufferedOutputStream( new FileOutputStream("saveme.xml"))); encoder.writeObject(saveme); encoder.close(); }
}
</source>
The TrafficLight Component
<source lang="java">
import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.beans.IntrospectionException; import java.beans.PropertyDescriptor; import java.beans.PropertyEditorSupport; import java.beans.SimpleBeanInfo; import java.util.TooManyListenersException; import java.util.Vector; import javax.swing.JComponent; public class TrafficLight extends JComponent {
public static String STATE_RED = "RED"; public static String STATE_YELLOW = "YELLOW"; public static String STATE_GREEN = "GREEN"; private static int DELAY = 3000; private String defaultLightState; private String currentLightState; private boolean debug; private Thread runner; private transient ActionListener listener; public TrafficLight() { defaultLightState = currentLightState = STATE_RED; setPreferredSize(new Dimension(100, 200)); } public void paintComponent(Graphics g) { super.paintComponent(g); // Paint the outline of the traffic light g.setColor(Color.white); g.fillRect(2, 2, 96, 196); // Debug if (debug) { System.out.println("Current light state is: " + currentLightState); } // Which light is on? if (currentLightState.equals(STATE_RED)) { g.setColor(Color.red); g.fillOval(30, 30, 40, 40); } else if (currentLightState.equals(STATE_YELLOW)) { g.setColor(Color.yellow); g.fillOval(30, 80, 40, 40); } else if (currentLightState.equals(STATE_GREEN)) { g.setColor(Color.green); g.fillOval(30, 130, 40, 40); } } public String getCurrentLightState() { return currentLightState; } public void setCurrentLightState(String currentLightState) { this.currentLightState = currentLightState; if (currentLightState != STATE_YELLOW) { if (debug) { System.out.println("Firing action event"); } ActionEvent ae = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, currentLightState); fireActionPerformed(ae); } repaint(); } public void setDefaultLightState(String defaultLightState) { this.defaultLightState = defaultLightState; currentLightState = defaultLightState; repaint(); } public String getDefaultLightState() { return defaultLightState; } public void setDebug(boolean debug) { this.debug = debug; } public boolean isDebug() { return debug; } public void initiate() { if (debug) { System.out.println("Initiate traffic light cycle!"); } startCycle(); } private void startCycle() { if (runner == null) { Runnable runnable = new Runnable() { public void run() { if (debug) { System.out.println("Started cycle"); } while (runner != null) { try { Thread.sleep(DELAY); } catch (InterruptedException e) { } if (currentLightState.equals(STATE_RED)) { setCurrentLightState(STATE_GREEN); } else if (currentLightState.equals(STATE_GREEN)) { setCurrentLightState(STATE_YELLOW); } else { setCurrentLightState(STATE_RED); } if (currentLightState.equals(defaultLightState)) { runner = null; } } } }; runner = new Thread(runnable); runner.start(); } } public void lightChange(ActionEvent x) { String command = x.getActionCommand(); if (debug) { System.out.println("Received event from traffic light: " + defaultLightState + " command: go to " + command); } if (command.equals(STATE_RED)) { if (!currentLightState.equals(STATE_GREEN)) { currentLightState = STATE_GREEN; repaint(); } } else if (command.equals(STATE_GREEN)) { if (!currentLightState.equals(STATE_RED)) { currentLightState = STATE_YELLOW; repaint(); try { Thread.sleep(DELAY); } catch (InterruptedException e) { } currentLightState = STATE_RED; repaint(); } } } public synchronized void removeActionListener(ActionListener l) { if (debug) { System.out.println("Deregistering listener"); } if (listener == l) { listener = null; } } public synchronized void addActionListener(ActionListener l) throws TooManyListenersException { if (debug) { System.out.println("Registering listener"); } if (listener == null) { listener = l; } else { throw new TooManyListenersException(); } } protected void fireActionPerformed(ActionEvent e) { if (debug) { System.out.println("Firing action event"); } if (listener != null) { listener.actionPerformed(e); } }
} class LightColorEditor extends PropertyEditorSupport {
public String[] getTags() { String values[] = { TrafficLight.STATE_RED, TrafficLight.STATE_YELLOW, TrafficLight.STATE_GREEN }; return values; }
} class TrafficLightBeanInfo extends SimpleBeanInfo {
public PropertyDescriptor[] getPropertyDescriptors() { try { PropertyDescriptor pd1 = new PropertyDescriptor("debug", TrafficLight.class); PropertyDescriptor pd2 = new PropertyDescriptor( "defaultLightState", TrafficLight.class); pd2.setPropertyEditorClass(LightColorEditor.class); PropertyDescriptor result[] = { pd1, pd2 }; return result; } catch (IntrospectionException e) { System.err.println("Unexpected exception: " + e); return null; } }
} class MyBean {
private transient Vector actionListeners; public synchronized void removeActionListener(ActionListener l) { if (actionListeners != null && actionListeners.contains(l)) { Vector v = (Vector) actionListeners.clone(); v.removeElement(l); actionListeners = v; } } public synchronized void addActionListener(ActionListener l) { Vector v = (actionListeners == null) ? new Vector(2) : (Vector) actionListeners.clone(); if (!v.contains(l)) { v.addElement(l); actionListeners = v; } } protected void fireActionPerformed(ActionEvent e) { if (actionListeners != null) { Vector listeners = actionListeners; int count = listeners.size(); for (int i = 0; i < count; i++) { ((ActionListener) listeners.elementAt(i)).actionPerformed(e); } } }
}
</source>