1. 被观察者(PropertyChangeListeners are fired on the event dispatching thread.) package org.jdesktop.application; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import javax.swing.SwingUtilities; /** * An encapsulation of the PropertyChangeSupport methods based on * java.beans.PropertyChangeSupport. PropertyChangeListeners are fired on the * event dispatching thread. * * <p> * Note: this class is only public because the so-called "fix" for javadoc bug * <a * href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4780441">4780441</a> * still fails to correctly document public methods inherited from a package * private class. */ public class AbstractBean { private final PropertyChangeSupport pcs; public AbstractBean() { pcs = new EDTPropertyChangeSupport(this); } /** * Add a PropertyChangeListener to the listener list. The listener is * registered for all properties and its {@code propertyChange} method will * run on the event dispatching thread. * <p> * If {@code listener} is null, no exception is thrown and no action is * taken. * * @param listener * the PropertyChangeListener to be added. * @see #removePropertyChangeListener * @see java.beans.PropertyChangeSupport#addPropertyChangeListener */ public void addPropertyChangeListener(PropertyChangeListener listener) { pcs.addPropertyChangeListener(listener); } /** * Remove a PropertyChangeListener from the listener list. * <p> * If {@code listener} is null, no exception is thrown and no action is * taken. * * @param listener * the PropertyChangeListener to be removed. * @see #addPropertyChangeListener * @see java.beans.PropertyChangeSupport#removePropertyChangeListener */ public void removePropertyChangeListener(PropertyChangeListener listener) { pcs.removePropertyChangeListener(listener); } /** * Add a PropertyChangeListener for a specific property. The listener will * be invoked only when a call on firePropertyChange names that specific * property. The same listener object may be added more than once. For each * property, the listener will be invoked the number of times it was added * for that property. If <code>propertyName</code> or <code>listener</code> * is null, no exception is thrown and no action is taken. * * @param propertyName * The name of the property to listen on. * @param listener * the PropertyChangeListener to be added * @see java.beans.PropertyChangeSupport#addPropertyChangeListener(String, * PropertyChangeListener) */ public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { pcs.addPropertyChangeListener(propertyName, listener); } /** * Remove a PropertyChangeListener for a specific property. If * <code>listener</code> was added more than once to the same event source * for the specified property, it will be notified one less time after being * removed. If <code>propertyName</code> is null, no exception is thrown and * no action is taken. If <code>listener</code> is null, or was never added * for the specified property, no exception is thrown and no action is * taken. * * @param propertyName * The name of the property that was listened on. * @param listener * The PropertyChangeListener to be removed * @see java.beans.PropertyChangeSupport#removePropertyChangeListener(String, * PropertyChangeListener) */ public synchronized void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { pcs.removePropertyChangeListener(propertyName, listener); } /** * An array of all of the {@code PropertyChangeListeners} added so far. * * @return all of the {@code PropertyChangeListeners} added so far. * @see java.beans.PropertyChangeSupport#getPropertyChangeListeners */ public PropertyChangeListener[] getPropertyChangeListeners() { return pcs.getPropertyChangeListeners(); } /** * Called whenever the value of a bound property is set. * <p> * If oldValue is not equal to newValue, invoke the {@code propertyChange} * method on all of the {@code PropertyChangeListeners} added so far, on the * event dispatching thread. * * @see #addPropertyChangeListener * @see #removePropertyChangeListener * @see java.beans.PropertyChangeSupport#firePropertyChange(String, Object, * Object) */ protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { if (oldValue != null && newValue != null && oldValue.equals(newValue)) { return; } pcs.firePropertyChange(propertyName, oldValue, newValue); } /** * Fire an existing PropertyChangeEvent * <p> * If the event's oldValue property is not equal to newValue, invoke the * {@code propertyChange} method on all of the {@code * PropertyChangeListeners} added so far, on the event dispatching thread. * * @see #addPropertyChangeListener * @see #removePropertyChangeListener * @see java.beans.PropertyChangeSupport#firePropertyChange(PropertyChangeEvent * e) */ protected void firePropertyChange(PropertyChangeEvent e) { pcs.firePropertyChange(e); } private static class EDTPropertyChangeSupport extends PropertyChangeSupport { EDTPropertyChangeSupport(Object source) { super(source); } public void firePropertyChange(final PropertyChangeEvent e) { if (SwingUtilities.isEventDispatchThread()) { super.firePropertyChange(e); } else { Runnable doFirePropertyChange = new Runnable() { public void run() { firePropertyChange(e); } }; SwingUtilities.invokeLater(doFirePropertyChange); } } } } 2. 观察者 /* * @(#)PropertyChangeListener.java 1.18 05/11/17 * * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ package java.beans; /** * A "PropertyChange" event gets fired whenever a bean changes a "bound" * property. You can register a PropertyChangeListener with a source * bean so as to be notified of any bound property updates. */ public interface PropertyChangeListener extends java.util.EventListener { /** * This method gets called when a bound property is changed. * @param evt A PropertyChangeEvent object describing the event source * and the property that has changed. */ void propertyChange(PropertyChangeEvent evt); }