# 如何编写列表选择监听器

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

当[列表](../components/list.html)或[表](../components/table.html)中的选择正在更改或刚刚更改时，会发生列表选择事件。列表选择事件是从实现 [`ListSelectionModel`](https://docs.oracle.com/javase/8/docs/api/javax/swing/ListSelectionModel.html) 接口的对象触发的。要获取表的列表选择模型对象，可以使用`getSelectionModel`方法或 getColumnModel（）。getSelectionModel（）。

要检测列表选择事件，请在相应的列表选择模型对象上注册侦听器。 `JList`类还为您提供了在列表本身上注册侦听器的选项，而不是直接在列表选择模型上注册。

本节将介绍两个示例，说明如何在选择模型上侦听列表选择事件。 [使用列表选择监听器](#eg)的示例列出了直接在列表上监听的示例。

在这两个示例中，您可以动态地将选择模式更改为三种支持的模式中的任何一种：

*   单选模式
*   单一间隔选择模式
*   多个间隔选择模式

以下是在 List 中运行的 ListSelectionDemo 示例的图片：

<center>![A snapshot of ListSelectionDemo, which demonstrates selection modes and list selection model.](img/f8e202290090e8544a5c17aa09067507.jpg)</center>

* * *

**Try this:** 

1.  单击“启动”按钮以使用 [Java™Web Start](http://www.oracle.com/technetwork/java/javase/javawebstart/index.html) （[下载 JDK 7 或更高版本](http://www.oracle.com/technetwork/java/javase/downloads/index.html)）运行 ListSelectionDemo。或者，要自己编译并运行示例，请参考[示例索引](../examples/events/index.html#ListSelectionDemo)。 [![Launches the ListSelectionDemo example](img/4707a69a17729d71c56b2bdbbb4cc61c.jpg)](https://docs.oracle.com/javase/tutorialJWS/samples/uiswing/ListSelectionDemoProject/ListSelectionDemo.jnlp) 

2.  选择并取消选择列表中的项目。选择项目所需的鼠标和键盘命令取决于外观。对于 Java 外观，单击鼠标左键开始选择，使用 shift 键连续扩展选择，并使用控制键不连续地扩展选择。请注意，有两种类型的选择：Lead 和 Anchor。 Lead 是焦点项目，Anchor 是突出显示的项目。按 ctrl 键并向上和向下移动时，即使实际选择未更改，导联选择也会导致触发事件。拖动鼠标会移动或扩展选择，具体取决于列表选择模式。

* * *

下面是在 Table 中运行的 TableListSelectionDemo 示例的图片：

<center>![A snapshot of TableListSelectionDemo, which demonstrates selection modes and list selection model.](img/763b5f51c4262665b9632cd59e42cf17.jpg)</center>

* * *

**Try this:** 

1.  单击“启动”按钮以使用 [Java™Web Start](http://www.oracle.com/technetwork/java/javase/javawebstart/index.html) （[下载 JDK 7 或更高版本](http://www.oracle.com/technetwork/java/javase/downloads/index.html)）运行 TableListSelectionDemo。或者，要自己编译并运行示例，请参考[示例索引](../examples/events/index.html#TableListSelectionDemo)。 [![Launches the TableListSelectionDemo example](img/4707a69a17729d71c56b2bdbbb4cc61c.jpg)](https://docs.oracle.com/javase/tutorialJWS/samples/uiswing/TableListSelectionDemoProject/TableListSelectionDemo.jnlp) 

2.  选择并取消选择表格中的项目。选择项目所需的鼠标和键盘命令取决于外观。对于 Java 外观，单击鼠标左键开始选择，使用 shift 键连续扩展选择，并使用控制键不连续地扩展选择。请注意，有两种类型的选择：Lead 和 Anchor。 Lead 是焦点项目，Anchor 是突出显示的项目。按 ctrl 键并向上或向下移动时，即使实际选择未更改，引线选择也会导致触发事件。拖动鼠标会移动或扩展选择，具体取决于列表选择模式。

* * *

您可以在 [``ListSelectionDemo.java``](../examples/events/ListSelectionDemoProject/src/events/ListSelectionDemo.java)中找到 ListSelectionDemo 的整个程序，并在 [``TableListSelectionDemo.java``](../examples/events/TableListSelectionDemoProject/src/events/TableListSelectionDemo.java)中找到 TableListSelectionDemo 的整个程序。

以下是来自`ListSelectionDemo`的代码，它设置选择模型并为其添加一个监听器：

```
...//where the member variables are defined
JList list;
    ...//in the init method:
    listSelectionModel = list.getSelectionModel();
    listSelectionModel.addListSelectionListener(
                            new SharedListSelectionHandler());
    ...

```

这里是监听器的代码，适用于所有可能的选择模式：

```
class SharedListSelectionHandler implements ListSelectionListener {
    public void valueChanged(ListSelectionEvent e) {
        ListSelectionModel lsm = (ListSelectionModel)e.getSource();

        int firstIndex = e.getFirstIndex();
        int lastIndex = e.getLastIndex();
        boolean isAdjusting = e.getValueIsAdjusting();
        output.append("Event for indexes "
                      + firstIndex + " - " + lastIndex
                      + "; isAdjusting is " + isAdjusting
                      + "; selected indexes:");

        if (lsm.isSelectionEmpty()) {
            output.append(" <none>");
        } else {
            // Find out which indexes are selected.
            int minIndex = lsm.getMinSelectionIndex();
            int maxIndex = lsm.getMaxSelectionIndex();
            for (int i = minIndex; i <= maxIndex; i++) {
                if (lsm.isSelectedIndex(i)) {
                    output.append(" " + i);
                }
            }
        }
        output.append(newline);
    }
}

```

此`valueChanged`方法显示事件报告的第一个和最后一个索引，事件的`isAdjusting`标志的值以及当前选择的索引。

请注意，事件报告的第一个和最后一个索引表示选择已更改的项目的包含范围。如果选择模式是多个间隔选择，则范围内的某些项目可能没有更改。如果用户仍在操作选择，则`isAdjusting`标志为`true`，如果用户已完成更改选择，则`false`。

传递到`valueChanged`的`ListSelectionEvent`对象仅表示选择已更改。该事件不包含有关当前选择的信息。因此，此方法查询选择模型以确定当前选择。

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

| 方法 | 目的 |
| :-- | :-- |
| [valueChanged（ListSelectionEvent）](https://docs.oracle.com/javase/8/docs/api/javax/swing/event/ListSelectionListener.html#valueChanged-javax.swing.ListSelectionEvent-) | 响应选择更改而调用。 |

| 方法 | 目的 |
| :-- | :-- |
| [对象 getSource（）](https://docs.oracle.com/javase/8/docs/api/java/util/EventObject.html#getSource--)
（`java.util.EventObject` 中的 _）_ | 返回触发事件的对象。如果直接在列表上注册列表选择侦听器，则每个事件的源都是列表。否则，源是选择模型。 |
| [int getFirstIndex（）](https://docs.oracle.com/javase/8/docs/api/javax/swing/event/ListSelectionEvent.html#getFirstIndex--) | 返回其选择值已更改的第一个项的索引。请注意，对于多个区间选择，保证第一个和最后一个项目已更改，但它们之间的项目可能没有。但是，当您按 ctrl 键并向上或向下移动时，即使实际选择未更改，导联选择也会导致触发事件。 |
| [int getLastIndex（）](https://docs.oracle.com/javase/8/docs/api/javax/swing/event/ListSelectionEvent.html#getLastIndex--) | 返回选择值已更改的最后一项的索引。请注意，对于多个区间选择，保证第一个和最后一个项目已更改，但它们之间的项目可能没有。但是，当您按 ctrl 键并上下移动时，即使实际选择未更改，前导选择也会导致触发事件。 |
| [boolean getValueIsAdjusting（）](https://docs.oracle.com/javase/8/docs/api/javax/swing/event/ListSelectionEvent.html#getValueIsAdjusting--) | 如果选择仍在变化，则返回`true`。许多列表选择侦听器仅对选择的最终状态感兴趣，并且当此方法返回`true`时可以忽略列表选择事件。 |

下表列出了使用列表选择侦听器的示例。

| 例 | 在哪里描述 | 笔记 |
| :-- | :-- | :-- |
| [`ListSelectionDemo`](../examples/events/index.html#ListSelectionDemo) | 这个部分 | 报告列表中发生的所有列表选择事件。允许用户动态更改选择模式。 |
| [`TableListSelectionDemo`](../examples/events/index.html#TableListSelectionDemo) | 这个部分 | 报告在表上发生的所有列表选择事件。允许用户动态更改选择模式。 |
| [`ListDemo`](../examples/components/index.html#ListDemo) | [如何使用列表](../components/list.html) | 侦听单选列表上的事件（不在其选择模型上）。根据是否在列表中选择任何项目，启用和禁用按钮。 |
| [`SplitPaneDemo`](../examples/components/index.html#SplitPaneDemo) | [如何使用列表](../components/list.html) | 侦听单选列表上的事件（不在其选择模型上）。 |
| [`SimpleTableSelectionDemo`](../examples/components/index.html#SimpleTableSelectionDemo) | [如何使用表格](../components/table.html) | 在一个表上使用两个不同的列表选择侦听器。一个侦听器侦听表列上的列表选择事件，另一个侦听器监听表行上的列表选择事件。 |