12.9.3 强制存储列表项的DefaultListModel和DefaultComboBoxModel

12.9.3 强制存储列表项的DefaultListModel和DefaultComboBoxModel

前面只是介绍了如何创建JListJComboBox对象,当调用JListJComboBox构造器时传入数组或Vector作为参数,这些数组元素或集合元素将会作为列表项。当使用JListJComboBox时常常还需要动态地增加、删除列表项。

JComboBox列表项的增加 插入 删除

对于JComboBox类,它提供了如下几个方法来增加、插入和删除列表项:

方法 描述
void addItem(E item) JComboBox中的添加一个列表项。
void insertItemAt(E item, int index) JComboBox的指定索引处插入一个列表项。
void removeAllItems() 删除JComboBox中的所有列表项。
void removeItem(Object anObject) 删除JComboBox中的指定列表项。
void removeItemAt(int anIndex) 删除JComboBox指定索引处的列表项

上面这些方法的参数类型是E,这是由于Java7JComboBoxJListListModel都増加了泛型支持,这些接口都有形如JComboBox<E>JList<E>ListModel<E>的泛型声明,因此它们里面的方法可使用E作为参数或返回值的类型
通过这些方法就可以增加、插入和删除JComboBox中的列表项。

JList没有提供增加 删除列表项的方法

JList并没有提供这些类似的方法。实际上,对于直接通过数组或Vector创建的JList对象,则很难向该JList中添加或删除列表项。

如果需要创建一个可以增加、删除列表项的JList对象,则应该在创建JList时显式使用DefaultListModel作为构造参数:

方法 描述
JList(ListModel<E> dataModel) Constructs a JList that displays elements from the specified, non-null, model.

通过DefaultListModel来实现向JList中添加 插入 删除元素

因为DefaultListModel作为JListModel,它负责维护JList组件的所有列表数据,所以可以通过向DefaultListModel中添加、删除元素来实现向JList对象中增加、删除列表项

DefaultListModel提供了如下几个方法来添加、插入 删除元素。

方法 描述
void add(int index, E element) 在该ListModel的指定位置处插入指定元素。
void addElement(E element) 将指定元素添加到该ListModel的末尾。
void insertElementAt(E element, int index) 在该ListModel的指定位置处插入指定元素
E remove(int index) 删除该ListModel中指定位置处的元素。
void removeAllElements() 删除该ListModel中的所有元素,并将其的大小设置为零。
boolean removeElement(Object obj) 删除该ListModel中第一个与参数匹配的元素。
void removeElementAt(int index) 删除该ListModel中指定索引处的元素。

上面这些方法有些功能是重复的,这是由于Java的历史原因造成的。如果通过DefaultListModel来创建JList组件,则就可以通过调用上面的这些方法来添加、删除DefaultListModel中的元素,从而实现对JList里列表项的增加、删除。下面程序示范了如何向JList中添加、删除列表项。

程序 使用DefaultListModel给JList 增加 插入 删除 列表项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import java.awt.BorderLayout;
import javax.swing.*;

public class DefaultListModelTest {
private JFrame mainWin = new JFrame("测试DefaultListModel");
// 定义一个JList对象
private JList<String> bookList;
// 定义一个DefaultListModel对象
private DefaultListModel<String> bookModel = new DefaultListModel<>();
private JTextField bookName = new JTextField(20);
private JButton removeBn = new JButton("删除选中图书");
private JButton addBn = new JButton("添加指定图书");

public void init() {
// 向bookModel中添加元素
bookModel.addElement("疯狂Java讲义");
bookModel.addElement("轻量级Java EE企业应用实战");
bookModel.addElement("疯狂Android讲义");
bookModel.addElement("疯狂Ajax讲义");
bookModel.addElement("经典Java EE企业应用实战");
// 根据DefaultListModel对象创建一个JList对象
bookList = new JList<>(bookModel);
// 设置最大可视高度
bookList.setVisibleRowCount(4);
// 只能单选
bookList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
// 为添加按钮添加事件监听器
addBn.addActionListener(evt -> {
// 当bookName文本框的内容不为空。
if (!bookName.getText().trim().equals("")) {
// 向bookModel中添加一个元素,
// 系统自动会向JList中添加对应的列表项
bookModel.addElement(bookName.getText());
}
});
// 为删除按钮添加事件监听器
removeBn.addActionListener(evt -> {
// 如果用户已经选中的一项
if (bookList.getSelectedIndex() >= 0) {
// 从bookModel中删除指定索引处的元素,
// 系统自动会删除JList对应的列表项
bookModel.removeElementAt(bookList.getSelectedIndex());
}
});
JPanel p = new JPanel();
p.add(bookName);
p.add(addBn);
p.add(removeBn);
// 添加bookList组件
mainWin.add(new JScrollPane(bookList));
// 将p面板添加到窗口中
mainWin.add(p, BorderLayout.SOUTH);
mainWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainWin.pack();
mainWin.setVisible(true);
}

public static void main(String[] args) {
new DefaultListModelTest().init();
}
}

上面程序中通过一个DefaultListModel创建了一个JList对象,然后在两个按钮的事件监听器中分别向DefaultListModel对象中添加、删除元素,从而实现了向JList对象中添加、删除列表项。
运行上面程序,会看到如图12.36所示的窗口。

为什么JComboBox提供添加删除列表项的方法 JList不提供

学生提问:为什么JComboBox提供了添加、删除列表项的方法?而JList没有提供添加、删除列表项的方法呢?
答:因为直接使用数组、Vector创建的JListJComboBox所对应的Model实规类不同。

  • 使用数组、Vector创建的JComboBoxModel类是DefaultComboBoxModel,
    • DefaultComboBoxModel是一个元素可变的集合类,所以使用数组、Vector创建的JComboBox可以直接派加、删除列表项,因此JComboBox提供了添加、删除列表项的方法;
  • 但使用数组、Vector创建的JList所对应的Model类分别是JList$1(JList的第一个匿名内部类)、JList$2(JList的第二个匿名内部类)
    • 这两个匿名内部类都是元素不可变的集合类,所以使用数组、Vector创建的JList不可以直接添加、删除列表项,因此JList没有提供添加、删除列表项的方法。
    • 如果想创建列表项可变的JList对象,则要显式使用DefaultListModel对象作为Model,而DefaultListModel才是元素可变的集合类,才可以直接通过修改DefaultListModel里的元素来改变JList里的列表项。

总结

DefaultListModelDefaultComboBoxModel是两个强制保存所有列表项的Model类,它们使用Vector来保存所有的列表项。
DefaultListModelTest程序中可以看出,DefaultListModel的用法和Vector的用法非常相似。实际上,DefaultListModelDefaultComboBoxModel从功能上来看,与一个Vector并没有太大的区别。如果要创建列表项可变的JList组件,使用DefaultListModel作为构造方法的参数即可

创建列表项可变的JComboBox组件,当然也可以显式使用DefaultComboBoxModel作为参数,但这并不是必需的,因为JComboBox已经默认使用DefaultComboBoxModel作为对应的model对象。