文档

Java™教程
隐藏目录
如何使用组合框
指南: 使用 Swing 创建 GUI
课程: 使用 Swing 组件
部分: 如何使用各种组件

如何使用组合框

一个JComboBox,它允许用户从多个选择中选择一个,可以有两种非常不同的形式。默认形式是不可编辑的组合框,它包括一个按钮和一个下拉值列表。第二种形式称为可编辑的组合框,它包括一个与之相邻的文本字段和一个小按钮。用户可以在文本字段中输入一个值,或者点击按钮显示一个下拉列表。以下是Java外观下这两种组合框的样式:

一个不可编辑的组合框
一个可编辑的组合框
一个不可编辑的组合框
一个可编辑的组合框
不可编辑的组合框,点击按钮之前(上方)
和之后
可编辑的组合框,点击箭头按钮之前和之后

组合框占用很少的屏幕空间,它们的可编辑(文本字段)形式对于让用户快速选择一个值而不限制用户只能选择显示的值非常有用。其他可以显示多个选择之一的组件包括一组单选按钮列表。一组单选按钮通常对用户来说最容易理解,但是当空间有限或者有多个选择可用时,组合框可能更合适。列表并不太吸引人,但当项目数量较大(比如超过20个)或者需要选择多个项目时,它们比组合框更合适。

由于可编辑和不可编辑的组合框非常不同,本节将分别介绍它们。本节包括以下主题:

使用不可编辑的组合框

这里展示的应用程序使用不可编辑的组合框来选择宠物图片:

一个不可编辑的组合框


试一试: 
  1. 点击“启动”按钮以使用Java™ Web Start下载JDK 7或更高版本)运行ComboBox Demo。或者,要自己编译和运行示例,请参考示例索引启动ComboBoxDemo示例

  2. 从组合框中选择一个动物名称以查看其图片。
  3. 将该程序的操作和GUI与使用单选按钮的程序进行比较:运行RadioButtonDemo(需要release 6)。您可能还想比较源代码:ComboBoxDemo.java vs. RadioButtonDemo.java

以下代码取自ComboBoxDemo.java,创建了一个不可编辑的组合框并进行设置:

String[] petStrings = { "鸟", "猫", "狗", "兔子", "猪" };

//创建一个下拉列表框,并选择索引为4的项。
//索引从0开始,所以4表示猪。
JComboBox petList = new JComboBox(petStrings);
petList.setSelectedIndex(4);
petList.addActionListener(this);

这个下拉列表框包含一个字符串数组,但你也可以使用图标。如果要将其他内容放入下拉列表框,或者自定义下拉列表框中的项的外观,你需要编写一个自定义渲染器。一个可编辑的下拉列表框还需要一个自定义编辑器。请参考提供自定义渲染器的信息和示例。

上述代码在下拉列表框上注册了一个动作监听器。要查看动作监听器的实现以及下拉列表框支持的其他类型的监听器,请参考处理下拉列表框上的事件

无论使用哪个构造函数,下拉列表框都使用一个下拉列表框模型来包含和管理其菜单中的项。当你使用数组或向量初始化下拉列表框时,下拉列表框会为你创建一个默认的模型对象。与其他 Swing 组件一样,你可以通过实现一个自定义模型(实现ComboBoxModel接口的对象)来部分自定义下拉列表框。  


注意: 

当为下拉列表框实现自定义模型时要小心。仅当数据模型实现了MutableComboBoxModel接口(ComboBoxModel的子接口)时,JComboBox中更改菜单中的项的方法,如insertItemAt,才能正常工作。请参考API表格以查看受影响的方法。

还有一点需要注意,即使对于不可编辑的下拉列表框,也要确保在下拉列表框的数据或状态发生更改时,你的自定义模型能够触发列表数据事件。即使是数据从不改变的不可变下拉列表框模型,在选择更改时也必须触发列表数据事件(一个CONTENTS_CHANGED事件)。获取列表数据事件触发代码的一种简单方法是将你的下拉列表框模型作为AbstractListModel的子类。


处理下拉列表框上的事件

下面是ComboBoxDemo.java中注册和实现动作监听器的代码:

public class ComboBoxDemo ... implements ActionListener {
    . . .
        petList.addActionListener(this) {
    . . .
    public void actionPerformed(ActionEvent e) {
        JComboBox cb = (JComboBox)e.getSource();
        String petName = (String)cb.getSelectedItem();
        updateLabel(petName);
    }
    . . .
}

这个动作监听器从组合框中获取新选择的项,使用它来计算图像文件的名称,并更新标签以显示图像。当用户从组合框的菜单中选择一个项时,组合框会触发一个动作事件。有关实现动作监听器的常规信息,请参阅如何编写动作监听器

组合框还会生成项目事件,当任何项的选择状态发生变化时会触发这些事件。在组合框中一次只能选择一个项,所以当用户进行新选择时,先前选择的项将被取消选择。因此,每当用户从菜单中选择一个不同的项时,会触发两个项目事件。如果用户选择相同的项,则不会触发项目事件。使用addItemListener在组合框上注册项目监听器。如何编写项目监听器提供了有关实现项目监听器的常规信息。

虽然JComboBox继承了用于注册低级事件的方法,如焦点、键盘和鼠标事件,但我们建议您不要在组合框上监听低级事件。原因如下:组合框是一个复合组件,它由两个或多个其他组件组成。组合框本身会触发高级事件,如动作事件。它的子组件会触发低级事件,如鼠标、键盘和焦点事件。低级事件和触发它们的子组件与外观和感觉有关。为了避免编写与外观和感觉有关的代码,您应该只在复合组件(如组合框)上监听高级事件。有关事件的信息,包括关于高级和低级事件的讨论,请参阅编写事件监听器

使用可编辑的组合框

下面是一个使用可编辑的组合框输入日期格式的演示应用程序的图片。

可编辑的组合框

试一试: 
  1. 点击“启动”按钮使用Java™ Web Start运行ComboBox2演示(下载JDK 7或更高版本)。或者,如果要自己编译和运行示例,请查阅示例索引启动ComboBoxDemo2示例

  2. 从组合框的菜单中选择一个新的模式。程序会重新格式化当前的日期和时间。
  3. 通过键入一个新模式并按Enter键来输入一个新模式。程序再次重新格式化当前的日期和时间。

以下代码取自ComboBoxDemo2.java,创建并设置了组合框:

String[] patternExamples = {
         "dd MMMMM yyyy",
         "dd.MM.yy",
         "MM/dd/yy",
         "yyyy.MM.dd G 'at' hh:mm:ss z",
         "EEE, MMM d, ''yy",
         "h:mm a",
         "H:mm:ss:SSS",
         "K:mm a,z",
         "yyyy.MMMMM.dd GGG hh:mm aaa"
};
. . .
JComboBox patternList = new JComboBox(patternExamples);
patternList.setEditable(true);
patternList.addActionListener(this);

这段代码与之前的示例非常相似,但需要解释一下。代码中加粗的那一行显式地启用了编辑功能,允许用户输入值。这是必需的,因为默认情况下,组合框是不可编辑的。这个特定的示例允许在组合框中进行编辑,因为其菜单不提供所有可能的日期格式化模式,只提供常用模式的快捷方式。

可编辑的组合框在用户从菜单中选择一个项或者用户输入回车键时触发动作事件。请注意,当用户在组合框中输入值时,菜单不会改变。如果需要,你可以很容易地编写一个动作监听器,每当用户输入一个唯一的值时,就向组合框的菜单中添加一个新项。

请参阅国际化了解更多关于日期和其他类型数据格式化的内容。

提供自定义渲染器

组合框使用一个渲染器来显示菜单中的每个项。如果组合框不可编辑,它还使用渲染器来显示当前选择的项。而可编辑的组合框则使用一个编辑器来显示选中的项。组合框的渲染器必须实现ListCellRenderer接口。组合框的编辑器必须实现ComboBoxEditor。本节展示如何为不可编辑的组合框提供自定义渲染器。

默认的渲染器知道如何渲染字符串和图标。如果你将其他对象放入组合框中,默认的渲染器会调用toString方法来提供要显示的字符串。你可以通过实现自己的ListCellRenderer来自定义组合框及其项的渲染方式。

下面是一个使用自定义渲染器的应用程序截图:

一个具有自定义渲染器的组合框

点击“启动”按钮以使用Java™ Web Start运行CustomComboBox演示(下载JDK 7或更高版本)。或者,如果要自行编译和运行示例,请参考示例索引

启动CustomComboBoxDemo示例

此示例的完整源代码位于CustomComboBoxDemo.java中。要获取它所需的图像文件,请参考示例索引

以下代码片段在示例中创建了一个ComboBoxRenderer实例(一个自定义类),并将该实例设置为组合框的渲染器:

JComboBox petList = new JComboBox(intArray);
. . .
ComboBoxRenderer renderer = new ComboBoxRenderer();
renderer.setPreferredSize(new Dimension(200, 130));
petList.setRenderer(renderer);
petList.setMaximumRowCount(3);

最后一行设置了组合框的最大行数,该行数确定了菜单显示时可见的项目数。如果组合框中的项目数量大于其最大行数,则菜单会出现滚动条。由于图标在菜单中相对较大,所以我们的代码将行数限制为3。下面是ComboBoxRenderer的实现,它将图标和文本并排显示:

class ComboBoxRenderer extends JLabel
                       implements ListCellRenderer {
    . . .
    public ComboBoxRenderer() {
        setOpaque(true);
        setHorizontalAlignment(CENTER);
        setVerticalAlignment(CENTER);
    }

    /*
     * 此方法找到与所选值对应的图像和文本,并返回设置好的标签以显示文本和图像。
     */
    public Component getListCellRendererComponent(
                                       JList list,
                                       Object value,
                                       int index,
                                       boolean isSelected,
                                       boolean cellHasFocus) {
        //获取所选索引。(index参数不总是有效的,所以只使用value。)
        int selectedIndex = ((Integer)value).intValue();

        if (isSelected) {
            setBackground(list.getSelectionBackground());
            setForeground(list.getSelectionForeground());
        } else {
            setBackground(list.getBackground());
            setForeground(list.getForeground());
        }

        //设置图标和文本。如果图标为空,则显示提示信息。
        ImageIcon icon = images[selectedIndex];
        String pet = petStrings[selectedIndex];
        setIcon(icon);
        if (icon != null) {
            setText(pet);
            setFont(list.getFont());
        } else {
            setUhOhText(pet + "(无可用图像)",
                        list.getFont());
        }

        return this;
    }
    . . .
}

作为 ListCellRendererComboBoxRenderer 实现了一个名为 getListCellRendererComponent 的方法,该方法返回一个组件,其 paintComponent 方法用于显示组合框及其每个项目。显示图像和图标的最简单方法是使用标签。所以 ComboBoxRenderer 是标签的子类,并返回自身。 getListCellRendererComponent 的实现配置了渲染器以显示当前选定的图标及其描述。

以下参数将传递给 getListCellRendererComponent

请注意,组合框和 列表 使用相同类型的渲染器 — ListCellRenderer。如果在您的程序中有意义,您可以通过在组合框和列表之间共享渲染器来节省时间。

组合框 API

以下表列出了常用的 JComboBox 构造函数和方法。您最有可能在 JComboBox 对象上调用的其他方法是从其超类继承的方法,例如 setPreferredSize。有关常用继承方法的表,请参见 JComponent API

使用组合框的 API 可分为两类:

设置或获取组合框菜单中的项目JComboBox()
JComboBox(ComboBoxModel)
JComboBox(Object[])
JComboBox(Vector)Vectorvoid addItem(Object)
void insertItemAt(Object, int)插入到MutableComboBoxModelObject getItemAt(int)
Object getSelectedItem()void removeAllItems()
void removeItemAt(int)
void removeItem(Object)MutableComboBoxModelint getItemCount()void setModel(ComboBoxModel)
ComboBoxModel getModel()void setAction(Action)
Action getAction()Action如何使用动作
自定义组合框的操作
方法或构造函数 目的
void addActionListener(ActionListener) 向组合框添加一个动作监听器。当用户从组合框的菜单中选择一个项目或在可编辑的组合框中按下Enter键时,会调用监听器的actionPerformed方法。
void addItemListener(ItemListener) 向组合框添加一个项目监听器。当组合框的任何项目的选择状态发生改变时,会调用监听器的itemStateChanged方法。
void setEditable(boolean)
boolean isEditable()
设置或获取用户是否可以在组合框中输入内容。
void setRenderer(ListCellRenderer)
ListCellRenderer getRenderer()
设置或获取负责在组合框中绘制选定项目的对象。渲染器仅在组合框不可编辑时使用。如果组合框可编辑,则使用编辑器来绘制选定的项目。
void setEditor(ComboBoxEditor)
ComboBoxEditor getEditor()
设置或获取负责在组合框中绘制和编辑选定项目的对象。编辑器仅在组合框可编辑时使用。如果组合框不可编辑,则使用渲染器来绘制选定的项目。

使用组合框的示例

此表格显示了使用 JComboBox 的示例以及这些示例所在的位置。

示例 所在位置 说明
ComboBoxDemo 本节 使用不可编辑的组合框。
ComboBoxDemo2 本节 使用可编辑的组合框。
CustomComboBoxDemo 本节 为组合框提供自定义渲染器。
TableRenderDemo 如何使用表格(将组合框用作编辑器 演示了如何将组合框用作表格单元格编辑器。

上一页:如何使用颜色选择器
下一页:如何制作对话框