如何使用组合框

JComboBox允许用户选择多个选项之一,它可以具有两种截然不同的形式。默认形式是不可编辑的组合框,它具有一个按钮和一个值的下拉列表。第二种形式称为可编辑组合框,其 Feature 是带有一个小按钮的文本字段。用户可以在文本字段中 Importing 值,或单击按钮以显示下拉列表。这是 Java 外观中两种形式的组合框:

不可编辑的组合框可编辑的组合框
不可编辑的组合框可编辑的组合框
不可编辑的组合框,在(顶部)之前

并单击按钮之后
可编辑组合框,之前和之后
单击箭头按钮

组合框只需要很小的屏幕空间,它们的可编辑(文本字段)形式对于让用户快速选择一个值而不会将用户限制在显示的值上很有用。可以显示许多选择的其他组件是radio buttonslists组。通常,用户最容易理解成组的单选按钮,但是当空间有限或有多个选择可用时,组合框可能更合适。列表并不是很吸引人,但是当项目数量很大(例如超过 20 个)或选择多个项目可能有效时,列表比组合框更合适。

由于可编辑和不可编辑的组合框非常不同,因此本节将它们分开对待。本节涵盖以下主题:

使用不可编辑的组合框

此处显示的应用程序使用不可编辑的组合框来选择宠物图片:

不可编辑的组合框

Try this:

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

String[] petStrings = { "Bird", "Cat", "Dog", "Rabbit", "Pig" };

//Create the combo box, select item at index 4.
//Indices start at 0, so 4 specifies the pig.
JComboBox petList = new JComboBox(petStrings);
petList.setSelectedIndex(4);
petList.addActionListener(this);

该组合框包含一个字符串 数组,但是您可以轻松地使用图标来代替。要将其他任何内容放入组合框或自定义组合框中项 Object 外观,则需要编写自定义渲染器。可编辑的组合框还需要自定义编辑器。有关信息和示例,请参考提供自定义渲染器

前面的代码在组合框上注册了一个动作侦听器。要查看动作侦听器的实现并了解组合框支持的其他类型的侦听器,请参阅在组合框上处理事件

无论使用哪种构造函数,组合框都将使用组合框模型来包含和 管理 其菜单中的项目。当您使用数组或向量初始化组合框时,组合框将为您创建一个默认模型对象。与其他 Swing 组件一样,您可以通过实现自定义模型来自定义组合框,该模型是实现ComboBoxModelinterface的对象。

Note:

为组合框实现自定义模型时要小心。更改组合框菜单中项 ObjectJComboBox方法(例如insertItemAt)仅在数据模型实现MutableComboBoxModelinterface(ComboBoxModel的子interface)时起作用。请参考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);
    }
    . . .
}

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

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

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

使用可编辑的组合框

这是演示应用程序的图片,该应用程序使用可编辑的组合框 Importing 用于格式化日期的 Pattern。

可编辑的组合框

Try this:

  • 单击启动按钮以使用Java™Web 开始(下载 JDK 7 或更高版本)运行 ComboBox2 演示。另外,要自己编译和运行示例,请查阅example index

  • 通过从组合框的菜单中选择一种来 Importing 新的 Pattern。该程序将重新格式化当前日期和时间。

  • Importing 一个新 Pattern,然后按 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);

该代码与前面的示例非常相似,但是需要一些解释。粗体代码行显式打开了编辑功能,允许用户键入值。这是必需的,因为默认情况下,组合框不可编辑。此特定示例允许在组合框上进行编辑,因为其菜单没有提供所有可能的日期格式 Pattern,而只是提供常用 Pattern 的快捷方式。

当用户从菜单中选择一个项目并且用户键入 Enter 时,可编辑的组合框将触发一个动作事件。请注意,当用户在组合框中 Importing 一个值时,菜单保持不变。如果需要,您可以轻松编写一个动作侦听器,每次用户键入一个唯一值时,该动作侦听器就会在组合框的菜单中添加一个新项。

请参阅Internationalization以了解有关格式化日期和其他类型数据的更多信息。

提供自定义渲染器

组合框使用渲染器在其菜单中显示每个项目。如果组合框不可编辑,则它还会使用渲染器显示当前选定的项目。另一方面,可编辑的组合框使用编辑器显示所选项目。组合框的渲染器必须实现 ListCellRendererinterface。组合框的编辑器必须实现ComboBoxEditor。本节说明如何为不可编辑的组合框提供自定义渲染器。

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

这是使用带有自定义渲染器的组合框的应用程序的图片:

带有自定义渲染器的组合框

单击启动按钮以使用Java™Web 开始(下载 JDK 7 或更高版本)运行 CustomComboBox 演示。另外,要自己编译和运行示例,请查阅example index

此示例的完整源代码在CustomComboBoxDemo.java中。要获取所需的图像文件,请查阅example index

示例中的以下语句创建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);
    }

    /*
     * This method finds the image and text corresponding
     * to the selected value and returns the label, set up
     * to display the text and image.
     */
    public Component getListCellRendererComponent(
                                       JList list,
                                       Object value,
                                       int index,
                                       boolean isSelected,
                                       boolean cellHasFocus) {
        //Get the selected index. (The index param isn't
        //always valid, so just use the value.)
        int selectedIndex = ((Integer)value).intValue();

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

        //Set the icon and text.  If icon was null, say so.
        ImageIcon icon = images[selectedIndex];
        String pet = petStrings[selectedIndex];
        setIcon(icon);
        if (icon != null) {
            setText(pet);
            setFont(list.getFont());
        } else {
            setUhOhText(pet + " (no image available)",
                        list.getFont());
        }

        return this;
    }
    . . .
}

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

这些参数传递给getListCellRendererComponent

  • JList list —在后台使用的列表对象,用于显示项目。该示例使用该对象的颜色设置前景色和背景色。

  • Object value —要渲染的对象。在此示例中为Integer

  • int index —要渲染的对象的索引。

  • boolean isSelected —指示是否选择了要渲染的对象。该示例使用它来确定要使用的颜色。

  • boolean cellHasFocus —指示要渲染的对象是否具有焦点。

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

组合框 API

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

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

设置或获取组合框菜单中的项目

MethodPurpose
JComboBox()

JComboBox(ComboBoxModel)
JComboBox(Object[])
JComboBox(Vector)
使用菜单中的指定项目创建一个组合框。最初使用默认构造函数创建的组合框在菜单中没有任何项目。其他每个构造函数都从其参数初始化菜单:模型对象,对象数组或对象Vector
void addItem(Object)
void insertItemAt(Object,int)
将指定的对象添加或插入到组合框的菜单中。 insert 方法将指定的对象放置在指定的索引处,从而将其插入到当前位于该索引处的对象之前。这些方法要求组合框的数据模型是MutableComboBoxModel的实例。
Object getItemAt(int)
Object getSelectedItem()
从组合框的菜单中获取一个项目。
void removeAllItems()
void removeItemAt(int)
void removeItem(Object)
从组合框的菜单中删除一个或多个项目。这些方法要求组合框的数据模型是MutableComboBoxModel的实例。
int getItemCount()获取组合框菜单中的项目数。
void setModel(ComboBoxModel)
ComboBoxModel getModel()
设置或获取提供组合框菜单中各项的数据模型。
void setAction(Action)
Action getAction()
设置或获取与组合框关联的Action。有关更多信息,请参见如何使用动作

自定义组合框的操作

方法或构造函数Purpose
void addActionListener(ActionListener)将动作侦听器添加到组合框。当用户从组合框的菜单中选择一项时,或者在用户按下 Enter 键时,在可编辑的组合框中,将调用侦听器的actionPerformed方法。
void addItemListener(ItemListener)将项目侦听器添加到组合框。当任何组合框项 Object 选择状态更改时,将调用侦听器的itemStateChanged方法。
void setEditable(boolean)

boolean isEditable()
设置或获取用户是否可以在组合框中键入。
void setRenderer(ListCellRenderer)
ListCellRenderer getRenderer()
设置或获取负责绘制组合框中所选项 Object 对象。仅当组合框不可编辑时才使用渲染器。如果组合框是可编辑的,则使用编辑器来绘制所选项目。
void setEditor(ComboBoxEditor)
ComboBoxEditor getEditor()
设置或获取负责绘画和编辑组合框中所选项 Object 对象。仅在组合框可编辑时才使用编辑器。如果组合框不可编辑,则使用渲染器绘制所选项目。

使用组合框的示例

下表显示了使用JComboBox的示例,并在其中描述了这些示例。

ExampleWhere DescribedNotes
ComboBoxDemoThis section使用不可编辑的组合框。
ComboBoxDemo2This section使用可编辑的组合框。
CustomComboBoxDemoThis section为组合框提供自定义渲染器。
TableRenderDemo如何使用表格(使用组合框作为编辑器)显示如何将组合框用作表格单元格编辑器。