这些Java教程是为JDK 8编写的。本页面描述的示例和实践不利用后续版本中引入的改进,并且可能使用不再可用的技术。
请参阅Java语言更改,了解Java SE 9及后续版本中更新的语言特性的摘要。
请参阅JDK发布说明,了解所有JDK版本的新功能、增强功能以及已删除或已弃用选项的信息。
JList
是向用户显示一组可选择的项目的组件,这些项目可以在一个或多个列中显示。列表可以有很多项目,所以它们通常被放在滚动窗格中。
除了列表,以下Swing组件也向用户提供了多个可选择的项目:组合框、菜单、表格以及一组复选框或单选按钮。要显示分层数据,请使用树。
下图显示了使用列表的两个应用程序。本节将以这些示例为基础进行后续讨论。
ListDialog (由ListDialogRunner使用) |
ListDemo |
有三种方式可以创建列表模型:
DefaultListModel
。AbstractListModel
并实现从ListModel
接口继承的getSize
和getElementAt
方法。下面是来自ListDialog.java
的代码,用于创建和设置列表:
list = new JList(data); //data的类型为Object[] list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); list.setLayoutOrientation(JList.HORIZONTAL_WRAP); list.setVisibleRowCount(-1); ... JScrollPane listScroller = new JScrollPane(list); 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 |
结合调用setLayoutOrientation
方法,调用setVisibleRowCount(-1)
可以使列表在屏幕上显示尽可能多的项目。另一个常见的用法是使用setVisibleRowCount
指定列表首选显示的行数。
列表使用ListSelectionModel
的实例来管理其选择。默认情况下,列表选择模型允许同时选择任意组合的项目。您可以通过在列表上调用setSelectionMode
方法来指定不同的选择模式。例如,ListDialog
和ListDemo
都将选择模式设置为SINGLE_SELECTION
(由ListSelectionModel
定义的常量),以便只能选择列表中的一个项目。下表描述了三种列表选择模式:
模式 | 描述 |
---|---|
SINGLE_SELECTION |
一次只能选择一个项目。当用户选择一个项目时,任何先前选择的项目都会先被取消选择。 |
SINGLE_INTERVAL_SELECTION |
可以选择多个连续的项目。当用户开始新的选择范围时,任何先前选择的项目都会先被取消选择。 |
MULTIPLE_INTERVAL_SELECTION |
默认。可以选择任意组合的项目。用户必须显式取消选择项目。 |
无论列表使用哪种选择模式,列表在选择改变时都会触发列表选择事件。您可以通过使用addListSelectionListener
方法将一个列表选择监听器添加到列表中来处理这些事件。列表选择监听器必须实现一个方法:valueChanged
。下面是ListDemo
中监听器的valueChanged
方法:
public void valueChanged(ListSelectionEvent e) { if (e.getValueIsAdjusting() == false) { if (list.getSelectedIndex() == -1) { //没有选择,禁用fire按钮。 fireButton.setEnabled(false); } else { //选择了,启用fire按钮。 fireButton.setEnabled(true); } } }
单个用户操作(如鼠标点击)可能会生成多个列表选择事件。如果用户仍在操作选择,则getValueIsAdjusting
方法返回true
。此特定程序只对用户操作的最终结果感兴趣,因此valueChanged
方法仅在getValueIsAdjusting
返回false
时执行操作。
由于列表处于单选模式,此代码可以使用getSelectedIndex
来获取刚刚选择的项目的索引。当选择模式允许选择多个项目时,JList
提供了其他方法来设置或获取选择。如果需要,您可以在列表本身上监听事件,也可以在列表的列表选择模型上监听事件。ListSelectionDemo是一个示例,演示了如何在列表选择模型上监听列表选择事件,并允许您动态更改列表的选择模式。
我们之前展示的ListDemo示例具有内容可能会更改的列表。您可以在ListDemo.java
中找到ListDemo的源代码。下面是ListDemo代码,它创建一个可变的列表模型对象,将初始项目放入其中,并使用列表模型创建列表:
listModel = new DefaultListModel(); listModel.addElement("Jane Doe"); listModel.addElement("John Smith"); listModel.addElement("Kathy Green"); list = new JList(listModel);
此特定程序使用的是Swing提供的DefaultListModel
的实例。尽管类名中含有"Default",但列表只有在程序明确指定时才具有DefaultListModel
。如果DefaultListModel
不符合您的需求,您可以编写一个自定义的列表模型,该模型必须符合ListModel
接口的规范。
下面的代码片段显示了在Fire按钮上注册的动作监听器的actionPerformed
方法。粗体代码行删除了列表中选定的项目。方法中的其余行在列表为空时禁用火按钮,并在列表不为空时进行另一选择。
public void actionPerformed(ActionEvent e) { int index = list.getSelectedIndex(); listModel.remove(index); int size = listModel.getSize(); if (size == 0) { //没有剩下的,禁用火焰。 fireButton.setEnabled(false); } else { //选择一个索引。 if (index == listModel.getSize()) { //在最后位置删除的项目 index--; } list.setSelectedIndex(index); list.ensureIndexIsVisible(index); } }
下面是共享Hire按钮和文本字段的动作监听器的actionPerformed
方法:
public void actionPerformed(ActionEvent e) { String name = employeeName.getText(); //用户没有输入唯一名称... if (name.equals("") || alreadyInList(name)) { Toolkit.getDefaultToolkit().beep(); employeeName.requestFocusInWindow(); employeeName.selectAll(); return; } int index = list.getSelectedIndex(); //获取选择的索引 if (index == -1) { //没有选择,所以插入到开头 index = 0; } else { //在选择的项目之后添加 index++; } listModel.insertElementAt(employeeName.getText(), index); //重置文本字段。 employeeName.requestFocusInWindow(); employeeName.setText(""); //选择新项目并使其可见。 list.setSelectedIndex(index); list.ensureIndexIsVisible(index); }
此代码使用列表模型的insertElementAt
方法在当前选择之后插入新名称,或者如果没有选择,则在列表开头插入。如果只想添加到列表的末尾,可以改为使用DefaultListModel
的addElement
方法。
每当列表中添加、删除或修改项目时,列表模型都会触发列表数据事件。有关监听这些事件的信息,请参考如何编写列表数据监听器。该部分包含了一个类似于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_WRAP 或VERTICAL_WRAP 布局方向,定义单元格如何换行。有关更多信息,请参见setLayoutOrientation(int)。该属性的默认值为VERTICAL 。 |
void setLayoutOrientation(int) int getLayoutOrientation() |
设置或获取列表单元格的布局方式。可能的布局格式由JList 定义的值VERTICAL (单列单元格;默认值)、HORIZONTAL_WRAP ("报纸"样式,内容水平然后垂直流动)和VERTICAL_WRAP ("报纸"样式,内容垂直然后水平流动)指定。 |
int getFirstVisibleIndex() int getLastVisibleIndex() |
获取第一个或最后一个可见项的索引。 |
void ensureIndexIsVisible(int) | 滚动,使指定索引在此列表所在的视口中可见。 |
setSelectionMode
int getAnchorSelectionIndex()
SINGLE_SELECTION
SINGLE_INTERVAL_SELECTION
MULTIPLE_INTERVAL_SELECTION
ListSelectionModel
void clearSelection()
类或方法 | 目的 |
---|---|
int getNextMatch(String, int, javax.swing.text.Position.Bias) | 在给定的起始索引处搜索列表中以指定字符串开头的项,并返回该索引(如果未找到字符串,则返回-1)。第三个参数指定搜索方向,可以是Position.Bias.Forward 或Position.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中创建列表。