如何使用列表

原文: https://docs.oracle.com/javase/tutorial/uiswing/components/list.html

JList 向用户显示一组项目,显示在一列或多列中,供选择。列表可以包含许多项目,因此它们通常放在滚动窗格中。

除了列表,以下 Swing 组件向用户显示多个可选项:组合框菜单复选框组单选按钮。要显示分层数据,请使用

下图显示了两个使用列表的应用程序。本节使用这些示例作为后续讨论的基础。

| A snapshot of ListDialog, which displays a simple list | A snapshot of ListDemo, which lets you add and remove list items | | ListDialog (由 ListDialogRunner 使用) | ListDemo |


Try this:

  1. 单击“启动”按钮以使用 Java™Web Start下载 JDK 7 或更高版本)运行 ListDemo。或者,要自己编译并运行示例,请参考示例索引Launches the ListDemo example

  2. 单击“启动”按钮以运行 ListDialogRunner。或者,要自己编译并运行示例,请参考示例索引Launches the ListDialogRunner example

  3. 要调出 ListDialog,请在标题为 Name That Baby 的窗口中单击选择一个新名称…按钮。 生成的对话框是一个 ListDialog 实例,它已被自定义为具有名称选择器的标题。

  4. 在 ListDemo 中,尝试添加(招聘)和删除(触发)一些项目。

This rest of this section discusses the following topics:

有三种方法可以创建列表模型:

  • DefaultListModel - 一切都非常适合你。本页中的示例使用DefaultListModel
  • AbstractListModel - 您管理数据并调用“fire”方法。对于这种方法,您必须子类化AbstractListModel并实现从ListModel接口继承的getSizegetElementAt方法。
  • ListModel - 你管理一切。

以下是 ListDialog.java 的代码,用于创建和设置其列表:

  1. list = new JList(data); //data has type Object[]
  2. list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
  3. list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
  4. list.setVisibleRowCount(-1);
  5. ...
  6. JScrollPane listScroller = new JScrollPane(list);
  7. listScroller.setPreferredSize(new Dimension(250, 80));

代码将数组传递给列表的构造器。该数组填充了从另一个对象传入的字符串。在我们的例子中,字符串碰巧是男孩的名字。

其他JList构造器允许您从Vector或从符合 ListModel 接口的对象初始化列表。如果使用数组或向量初始化列表,构造器将隐式创建默认列表模型。默认列表模型是不可变的 - 您无法添加,删除或替换列表中的项目。要创建可以单独更改项目的列表,请将列表的模型设置为可变列表模型类的实例,例如 DefaultListModel 的实例。您可以在创建列表时或通过调用setModel方法设置列表的模型。有关示例,请参阅向列表添加项目和从列表中删除项目

setSelectionMode的调用指定了用户可以选择的项目数,以及它们是否必须是连续的;下一节将向您介绍有关选择模式的更多信息。

setLayoutOrientation的调用允许列表在多列中显示其数据。值JList.HORIZONTAL_WRAP指定列表应在包装到新行之前从左到右显示其项目。另一个可能的值是JList.VERTICAL_WRAP,它指定在包装到新列之前从上到下(照例)显示数据。下图显示了这两种包装可能性以及默认值JList.VERTICAL

| HORIZONTAL_WRAP | VERTICAL_WRAP | VERTICAL | | HORIZONTAL_WRAP | VERTICAL_WRAP | VERTICAL |

结合对setLayoutOrientation的调用,调用setVisibleRowCount(-1)使列表显示屏幕上可用空间中可能的最大项目数。 setVisibleRowCount的另一个常见用途是在列表的滚动窗格中指定列表优先显示的行数。

列表使用 ListSelectionModel 的实例来管理其选择。默认情况下,列表选择模型允许一次选择任何项目组合。您可以通过调用列表中的setSelectionMode方法指定其他选择模式。例如,ListDialogListDemo都将选择模式设置为SINGLE_SELECTION(由ListSelectionModel定义的常量),以便只能选择列表中的一个项目。下表描述了三种列表选择模式:

模式 描述
SINGLE_SELECTION

Single selection means only one item can be selected at once

| 一次只能选择一个项目。当用户选择项目时,首先取消选择任何先前选择的项目。 | | SINGLE_INTERVAL_SELECTION Single interval selection means multiple, contiguous items can be selected at once

| 可以选择多个连续的项目。当用户开始新的选择范围时,首先取消选择任何先前选择的项目。 | | MULTIPLE_INTERVAL_SELECTION Multiple interval selection means any combination of items can be selected at once

| 默认。可以选择任何项目组合。用户必须明确取消选择项目。 |

无论您的列表使用哪种选择模式,只要选择更改,列表就会触发列表选择事件。您可以通过使用addListSelectionListener方法将列表选择监听器添加到列表来处理这些事件。列表选择监听器必须实现一个方法:valueChanged。这是ListDemo中监听器的valueChanged方法:

  1. public void valueChanged(ListSelectionEvent e) {
  2. if (e.getValueIsAdjusting() == false) {
  3. if (list.getSelectedIndex() == -1) {
  4. //No selection, disable fire button.
  5. fireButton.setEnabled(false);
  6. } else {
  7. //Selection, enable the fire button.
  8. fireButton.setEnabled(true);
  9. }
  10. }
  11. }

可以从单个用户操作(例如鼠标单击)生成许多列表选择事件。如果用户仍在操作选择,则getValueIsAdjusting方法返回true。此特定程序仅对用户操作的最终结果感兴趣,因此valueChanged方法仅在getValueIsAdjusting返回false时才执行某些操作。

由于列表处于单选模式,因此该代码可以使用getSelectedIndex来获取刚刚选择的项目的索引。当选择模式允许选择多个项目时,JList设置或获取选择提供其他方法。如果需要,您可以在列表的列表选择模型上而不是列表本身上侦听事件。 ListSelectionDemo 是一个示例,显示如何在列表选择模型上侦听列表选择事件,并允许您动态更改列表的选择模式。

我们之前显示的 ListDemo 示例具有一个列表,其内容可以更改。您可以在 ListDemo.java 中找到 ListDemo 的源代码。下面是 ListDemo 代码,它创建一个可变列表模型对象,将初始项放入其中,并使用列表模型创建列表:

  1. listModel = new DefaultListModel();
  2. listModel.addElement("Jane Doe");
  3. listModel.addElement("John Smith");
  4. listModel.addElement("Kathy Green");
  5. list = new JList(listModel);

这个特殊程序使用DefaultListModel的实例,这是 Swing 提供的一个类。尽管有类名,但列表没有DefaultListModel,除非你的程序明确地这样做。如果DefaultListModel不符合您的需要,您可以编写自定义列表模型,该模型必须符合ListModel接口。

以下代码段显示了在 Fire 按钮上注册的动作监听器的actionPerformed方法。粗体代码行将删除列表中的选定项。如果列表现在为空,则方法中的其余行将禁用触发按钮,如果不是,则进行另一个选择。

  1. public void actionPerformed(ActionEvent e) {
  2. int index = list.getSelectedIndex();
  3. listModel.remove(index);
  4. int size = listModel.getSize();
  5. if (size == 0) { //Nobody's left, disable firing.
  6. fireButton.setEnabled(false);
  7. } else { //Select an index.
  8. if (index == listModel.getSize()) {
  9. //removed item in last position
  10. index--;
  11. }
  12. list.setSelectedIndex(index);
  13. list.ensureIndexIsVisible(index);
  14. }
  15. }

这是 Hire 按钮和文本字段共享的动作监听器的actionPerformed方法:

  1. public void actionPerformed(ActionEvent e) {
  2. String name = employeeName.getText();
  3. //User did not type in a unique name...
  4. if (name.equals("") || alreadyInList(name)) {
  5. Toolkit.getDefaultToolkit().beep();
  6. employeeName.requestFocusInWindow();
  7. employeeName.selectAll();
  8. return;
  9. }
  10. int index = list.getSelectedIndex(); //get selected index
  11. if (index == -1) { //no selection, so insert at beginning
  12. index = 0;
  13. } else { //add after the selected item
  14. index++;
  15. }
  16. listModel.insertElementAt(employeeName.getText(), index);
  17. //Reset the text field.
  18. employeeName.requestFocusInWindow();
  19. employeeName.setText("");
  20. //Select the new item and make it visible.
  21. list.setSelectedIndex(index);
  22. list.ensureIndexIsVisible(index);
  23. }

此代码使用列表模型的insertElementAt方法在当前选择之后插入新名称,如果不存在选择,则在列表的开头插入。如果您只想添加到列表的末尾,则可以使用DefaultListModeladdElement方法。

每当在列表中添加,删除或修改项目时,列表模型都会触发列表数据事件。有关侦听这些事件的信息,请参阅如何编写列表数据监听器。该部分包含一个类似于ListDemo的示例,但添加了在列表中向上或向下移动项目的按钮。

列表使用称为单元格渲染器的对象来显示其每个项目。默认的单元格渲染器知道如何显示字符串和图标,并通过调用toString显示Object。如果要更改默认渲染器显示图标或字符串的方式,或者如果您希望行为与toString提供的行为不同,则可以实现自定义单元格渲染器。执行以下步骤为列表提供自定义单元格渲染器:

  • 编写一个实现 ListCellRenderer 接口的类。
  • 创建类的实例,并使用实例作为参数调用列表的setCellRenderer

我们没有提供带有自定义单元格渲染器的列表示例,但我们确实有一个带有自定义渲染器的组合框示例 - 组合框使用与列表相同类型的渲染器。请参阅提供自定义渲染器中描述的示例。

下表列出了常用的JList构造器和方法。您最有可能在JList对象上调用的其他方法是其超类提供的setPreferredSize。有关常用继承方法的表,请参见 JComponent API

列表的大部分操作由其他对象管理。列表中的项目由列表模型对象管理,选择由列表选择模型对象管理,并且大多数程序将列表放在滚动窗格中以处理滚动。在大多数情况下,您无需担心模型,因为JList会根据需要创建模型,并使用JList的便捷方法隐式地与它们进行交互。

也就是说,使用列表的 API 属于以下类别:

方法或构造器 目的
JList(ListModel)

JList(Object []) JList(Vector) JList() | 创建一个包含指定的初始列表项的列表。第二个和第三个构造器隐式创建一个不可变的ListModel;你不应该随后修改传入的数组或Vector。 | | void setModel(ListModel) ListModel getModel() | 设置或获取包含列表内容的模型。 | | void setListData(Object []) void setListData(Vector) | 设置列表中的项目。这些方法隐式地创建了一个不可变的ListModel。 |

方法 目的
void setVisibleRowCount(int)

int getVisibleRowCount() | 设置或获取visibleRowCount属性。对于VERTICAL布局方向,这将设置或获取要显示的首选行数,而无需滚动。对于HORIZONTAL_WRAPVERTICAL_WRAP布局方向,它定义了细胞如何包裹。有关更多信息,请参见 setLayoutOrientation(int)。此属性的默认值为VERTICAL。 | | void setLayoutOrientation(int) int getLayoutOrientation() | 设置或获取列表单元格的布局。可能的布局格式由JList定义的值VERTICAL(单个单元格列;默认值),HORIZONTAL_WRAP(“报纸”样式,内容水平然后垂直流动)和VERTICAL_WRAP( “报纸”风格,内容垂直然后水平流动)。 | | int getFirstVisibleIndex() int getLastVisibleIndex() | 获取第一个或最后一个可见项的索引。 | | void ensureIndexIsVisible(int) | 滚动以使指定的索引在此列表所在的视口中可见。 |

方法 目的
void addListSelectionListener(ListSelectionListener) 注册以接收选择更改的通知。
void setSelectedIndex(int)

void setSelectedIndices(int []) void setSelectedValue(Object,boolean) void setSelectionInterval(int,int) | 如图所示设置当前选择。使用setSelectionMode设置可接受的选择范围。 boolean 参数指定列表是否应尝试滚动自身以使所选项目可见。 | | int getAnchorSelectionIndex() int getLeadSelectionIndex() int getSelectedIndex() int getMinSelectionIndex() int getMaxSelectionIndex() int [] getSelectedIndices() Object getSelectedValue() Object [] getSelectedValues () | 获取有关当前选择的信息,如图所示。 | | void setSelectionMode(int) int getSelectionMode() | 设置或获取选择模式。可接受的值为:SINGLE_SELECTIONSINGLE_INTERVAL_SELECTIONMULTIPLE_INTERVAL_SELECTION(默认值),它们在ListSelectionModel中定义。 | | void clearSelection() boolean isSelectionEmpty() | 设置或获取是否选择了任何项目。 | | boolean isSelectedIndex(int) | 确定是否选择了指定的索引。 |

类或方法 目的
int getNextMatch(String,int,javax.swing.text.Position.Bias) 给定起始索引,在列表中搜索以指定字符串开头并返回该索引的项(如果未找到该字符串,则返回-1)。指定搜索方向的第三个参数可以是Position.Bias.ForwardPosition.Bias.Backward。例如,如果您有一个 6 项目列表,getNextMatch("Matisse", 5, javax.swing.text.Position.Bias.Forward)在索引 5 处的项目中搜索字符串“Matisse”,然后(如果需要)在索引 0,索引 1 处搜索,依此类推。
void setDragEnabled(boolean)

boolean getDragEnabled() | 设置或获取确定是否启用自动拖动处理的属性。有关详细信息,请参阅拖放和数据传输。 |

此表显示了使用JList的示例以及描述这些示例的示例。

在哪里描述 笔记
SplitPaneDemo 如何使用分割窗格 包含单选,不可变列表。
ListDemo 这个部分 演示如何在运行时从列表中添加和删除项目。
ListDialog 本节如何使用 BoxLayout 使用单选列表实现模式对话框。
ListDataEventDemo 如何编写列表数据监听器 演示在列表模型上侦听列表数据事件。
ListSelectionDemo 如何编写列表选择监听器 包含共享相同选择模型的列表和表。您可以动态选择选择模式。
SharedModelDemo 使用型号 修改ListSelectionDemo,使列表和表共享相同的数据模型。
CustomComboBoxDemo 提供自定义渲染器 演示如何为组合框提供自定义渲染器。由于列表和组合框使用相同类型的渲染器,因此您可以使用您在其中学习的内容将其应用于列表。实际上,列表和组合框可以共享渲染器。

请参阅使用 JavaFX UI 控件:列表视图教程,了解如何在 JavaFX 中创建列表。