# 如何编写属性更改侦听器

> 原文： [https://docs.oracle.com/javase/tutorial/uiswing/events/propertychangelistener.html](https://docs.oracle.com/javase/tutorial/uiswing/events/propertychangelistener.html)

只要 _ 绑定属性 _ 的值发生变化 _bean_ - 一个符合 JavaBeans™规范的组件，就会发生属性更改事件。您可以从 Java Tutorial 的 [JavaBeans](../../javabeans/) 路径中找到有关 bean 的更多信息。所有 Swing 组件也都是 bean。

通过其 _get_ 和 _set_ 方法访问 JavaBeans 属性。例如，`JComponent`具有 _ 字体 _ 属性，可通过`getFont`和`setFont`方法访问。

除了 _get_ 和 _set_ 方法之外，绑定属性在其值更改时触发属性更改事件。有关更多信息，请参阅 JavaBeans 路径中的[绑定属性](../../javabeans/writing/properties.html#bound)页面。

通常需要属性更改侦听器的一些场景包括：

*   您已实现格式化文本字段，并需要一种方法来检测用户何时输入新值。您可以在格式化文本字段上注册属性更改侦听器，以侦听 _ 值 _ 属性的更改。有关此示例，请参见[如何使用格式化文本字段](../components/formattedtextfield.html#value)中的`FormattedTextFieldDemo`。
*   您已经实现了一个对话框，需要知道用户何时单击了对话框的某个按钮或更改了对话框中的选项。有关在选项窗格上注册属性更改侦听器以侦听对 _ 值 _ 属性的更改的示例，请参阅[如何创建对话框](../components/dialog.html#stayup)中的`DialogDemo`。您还可以查看[如何使用文件选择器](../components/filechooser.html#advancedexample)中的`FileChooserDemo2`，了解如何注册属性更改侦听器以侦听对 _directoryChanged_ 和 _selectedFileChanged 的更改的示例 _ 属性。
*   当具有焦点的组件发生更改时，您需要得到通知。您可以在键盘焦点管理器上注册属性更改侦听器，以侦听对 _focusOwner_ 属性的更改。有关此示例，请参见[如何使用焦点子系统](../misc/focus.html#trackingFocus)中的`TrackFocusDemo`和`DragPictureDemo`。

虽然这些是属性更改侦听器的一些常见用法，但您可以在符合 JavaBeans 规范的任何组件的 bound 属性上注册属性更改侦听器。

您可以通过两种方式注册属性更改侦听器。第一种使用方法`addPropertyChangeListener(PropertyChangeListener)`。以这种方式注册侦听器时，会通知您对该对象的每个绑定属性的每次更改。在`propertyChange`方法中，您可以使用`PropertyChangeEvent` `getPropertyName`方法获取已更改的属性的名称，如以下代码段所示：

```
KeyboardFocusManager focusManager =
   KeyboardFocusManager.getCurrentKeyboardFocusManager();
focusManager.addPropertyChangeListener(new FocusManagerListener());
...
public FocusManagerListener implements PropertyChangeListener {
    public void propertyChange(PropertyChangeEvent e) {
        String propertyName = e.getPropertyName();
        if ("focusOwner".equals(propertyName) {
            ...
        } else if ("focusedWindow".equals(propertyName) {
            ...
        }
    }
    ...
}

```

注册属性更改侦听器的第二种方法使用方法`addPropertyChangeListener(String, PropertyChangeListener)`。 `String`参数是属性的名称。使用此方法意味着只有在特定属性发生更改时才会收到通知。因此，例如，如果您注册了一个属性更改侦听器，如下所示：

```
aComponent.addPropertyChangeListener("font",
                                     new FontListener());

```

`FontListener`仅在组件的 _ 字体 _ 属性值发生变化时才会收到通知。当 _transferHandler_ ， _opaque_ ， _border_ 或任何其他属性的值发生变化时，_ 不会 _ 收到通知。

以下示例说明如何使用`addPropertyChangeListener`的双参数版本在格式化文本字段的 _ 值 _ 属性上注册属性更改侦听器：

```
//...where initialization occurs:
double amount;
JFormattedTextField amountField;
...
amountField.addPropertyChangeListener("value",
                                      new FormattedTextFieldListener());
...
class FormattedTextFieldListener implements PropertyChangeListener {
    public void propertyChanged(PropertyChangeEvent e) {
        Object source = e.getSource();
        if (source == amountField) {
            amount = ((Number)amountField.getValue()).doubleValue();
            ...
        }
        ...//re-compute payment and update field...
    }
}

```

| 方法 | 目的 |
| :-- | :-- |
| [addPropertyChangeListener（PropertyChangeListener）](https://docs.oracle.com/javase/8/docs/api/java/awt/Component.html#addPropertyChangeListener-java.beans.PropertyChangeListener-) | 将属性更改侦听器添加到侦听器列表。 |
| [addPropertyChangeListener（String，PropertyChangeListener）](https://docs.oracle.com/javase/8/docs/api/java/awt/Component.html#addPropertyChangeListener-java.lang.String-java.beans.PropertyChangeListener-) | 为特定属性添加属性更改侦听器。只有在指定属性发生更改时才会调用侦听器。 |

_ 因为`PropertyChangeListener`只有一个方法，所以它没有相应的适配器类。_

| 方法 | 目的 |
| :-- | :-- |
| [propertyChange（PropertyChangeEvent）](https://docs.oracle.com/javase/8/docs/api/java/beans/PropertyChangeListener.html#propertyChange-java.beans.PropertyChangeEvent-) | 当被监听的 bean 更改绑定属性时调用。 |

| 方法 | 目的 |
| :-- | :-- |
| [Object getNewValue（）](https://docs.oracle.com/javase/8/docs/api/java/beans/PropertyChangeEvent.html#getNewValue--)
[Object getOldValue（）](https://docs.oracle.com/javase/8/docs/api/java/beans/PropertyChangeEvent.html#getOldValue--) | 分别返回属性的新值或旧值。 |
| [String getPropertyName（）](https://docs.oracle.com/javase/8/docs/api/java/beans/PropertyChangeEvent.html#getPropertyName--) | 返回已更改的属性的名称。 |
| [void setPropagationId（）](https://docs.oracle.com/javase/8/docs/api/java/beans/PropertyChangeEvent.html#setPropagationId--) | 获取或设置传播 ID 值。保留供将来使用。 |

下表列出了使用属性更改侦听器的示例。

| 例 | 在哪里描述 | 笔记 |
| :-- | :-- | :-- |
| [`FormattedTextFieldDemo`](../examples/components/index.html#FormattedTextFieldDemo) | [如何使用格式化文本字段](../components/formattedtextfield.html#value) | 属性更改侦听器在多个格式化文本字段上注册，以跟踪 _ 值 _ 属性的更改。 |
| [`DialogDemo`](../examples/components/index.html#DialogDemo) | [如何制作对话](../components/dialog.html#stayup) | [`CustomDialog`](../examples/components/DialogDemoProject/src/components/CustomDialog.java) 类在选项窗格上注册属性更改侦听器以侦听 _ 值 _ 和 _inputValue_ 属性。 |
| [`FileChooserDemo2`](../examples/components/index.html#FileChooserDemo2) | [如何使用文件选择器](../components/filechooser.html#advancedexample) | [`ImagePreview`](../examples/components/FileChooserDemo2Project/src/components/ImagePreview.java) 类在文件选择器上注册属性更改侦听器，以侦听 _directoryChanged_ 和 _selectedFileChanged_ 属性。 |
| [`TrackFocusDemo`](../examples/misc/index.html#TrackFocusDemo) | [如何使用焦点子系统](../misc/focus.html#trackingFocus) | 在键盘焦点管理器上注册属性更改侦听器，以跟踪 _focusOwner_ 属性的更改。 |