第17章 清單
由JList類代表的Swing清單顯示一個可選取對象清單,它支援三種選取模式:單選取、單間隔選取和多間隔選取。
JList類把維護和繪制清單的工作委托給一個對象來完成。一個清單的模型維護一個對象清單,清單單元繪制器将這些對象繪制在清單單元中。
預設情況下,清單單元繪制器是DefaultListCellRenderrer的執行個體,它繪制表17-1中列出的對象。圖示和字元串按原樣顯示,而所有其他類型對象的繪制方式是:通過顯示從這些對象的toString傳回的字元串來繪制這些對象。
例 17-1 一個簡單的清單樣例
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
public class Test extends JApplet {
public void init() {
Container contentPane = getContentPane();
Object[] items = { "item one", "item two", "item three",
"item four", "item five", "item six",
"item seven", "item eight",
"item nine", "item ten" };
JList list = new JList(items);
JScrollPane sp = new JScrollPane(list);
list.setVisibleRowCount(7);
contentPane.setLayout(new FlowLayout());
contentPane.add(sp);
}
17.1 清單模型
例 17-2 一個帶有預設清單模型的清單
private JList list = new JList();
String[] items = { "item[0]", "item[1]", "item[2]",
"item[3]", "item[4]", "item[5]",
"item[6]", "item[7]",
"item[8]", "item[9]" };
JPanel controlPanel = new ControlPanel(list);
contentPane.add(controlPanel, BorderLayout.NORTH);
contentPane.add(new JScrollPane(list),
BorderLayout.CENTER);
populateList();
public void populateList() {
DefaultListModel model = new DefaultListModel();
for(int i=0; i < items.length; ++i)
model.addElement(items[i]);
list.setModel(model);
class ControlPanel extends JPanel {
JButton remove = new JButton("remove selected items");
JButton add = new JButton("add item");
public ControlPanel(final JList list) {
add(remove);
add(add);
remove.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int[] selected = list.getSelectedIndices();
DefaultListModel model =
(DefaultListModel)list.getModel();
for(int i=0; i < selected.length; ++i) {
model.removeElementAt(selected[i] - i);
});
add.addActionListener(new ActionListener() {
final DefaultListModel model =
String s = JOptionPane.showInputDialog(
list,
"Enter item text:");
model.addElement(s);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
list.ensureIndexIsVisible(
model.getSize()-1);
17.1.1 AbstractListModel
17.1.2 DefaultListModel
17.2 清單選取
17.3 清單單繪制器
例17-3 實作一個定制清單單元繪制器
import javax.swing.border.*;
private String[] names = new String[] {
"baseball player", "basketball player",
"beach player", "chef",
"hockey player", "software developer",
"construction worker", "martial artist",
"soccer", "movie star"
};
private String[] pics = new String[] {
"baseball.gif", "basketball.gif",
"beach_umbrella.gif", "dining.gif",
"hockey.gif", "mad_hacker.gif",
"men_at_work.gif", "punch.gif",
"soccer.gif", "filmstrip.gif"
ListModel model =
new NameAndPictureListModel(names, pics);
ListCellRenderer renderer =
new NameAndPictureListCellRenderer();
JList list = new JList(model);
list.setCellRenderer(renderer);
list.setVisibleRowCount(5);
contentPane.add(new JScrollPane(list));
class NameAndPictureListModel extends DefaultListModel {
public NameAndPictureListModel(String[] names,String[] pics) {
for(int i=0; i < names.length; ++i) {
addElement(new Object[] {
names[i], new ImageIcon(pics[i]) } );
public String getName(Object object) {
Object[] array = (Object[])object;
return (String)array[0];
public Icon getIcon(Object object) {
return (Icon)array[1];
class NameAndPictureListCellRenderer extends JLabel
implements ListCellRenderer {
private Border
lineBorder = BorderFactory.createLineBorder(Color.red, 2),
emptyBorder = BorderFactory.createEmptyBorder(2,2,2,2);
public NameAndPictureListCellRenderer() {
setOpaque(true);
public Component getListCellRendererComponent(
JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus) {
NameAndPictureListModel model =
(NameAndPictureListModel)list.getModel();
setText(model.getName(value));
setIcon(model.getIcon(value));
if(isSelected) {
setForeground(list.getSelectionForeground());
setBackground(list.getSelectionBackground());
else {
setForeground(list.getForeground());
setBackground(list.getBackground());
if(cellHasFocus) setBorder(lineBorder);
else setBorder(emptyBorder);
return this;
17.3.1 JList屬性
17.3.2 JList事件
例17-4 檢測清單選取的調整值
list.addListSelectionListener(
new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
String s;
if(e.getValueIsAdjusting()) {
s = "adjusting selection ...";
s = "selection from " + e.getFirstIndex() +
" to " + e.getLastIndex();
showStatus(s);
例17-5 處理清單選取事件
private ControlPanel controlPanel;
JPanel listPanel = new JPanel();
list.setPrototypeCellValue("MMMMMMM");
controlPanel = new ControlPanel(list);
controlPanel.update();
listPanel.setBorder(BorderFactory.createEtchedBorder());
listPanel.add(new JScrollPane(list));
contentPane.add(listPanel, BorderLayout.CENTER);
private JComboBox mode = new JComboBox();
private JButton clear = new JButton("clear selection");
private String single = "SINGLE_SELECTION",
singleInterval = "SINGLE_INTERVAL_SELECTION",
multipleInterval = "MULTIPLE_INTERVAL_SELECTION";
private JLabel leadLabel = new JLabel(),
anchorLabel = new JLabel(),
minLabel = new JLabel(),
maxLabel = new JLabel(),
selIndicesLabel = new JLabel();
private JList list;
public ControlPanel(JList l) {
JPanel top = new JPanel(),
mid = new JPanel(),
bottom = new JPanel();
this.list = l;
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
setBorder(BorderFactory.createEtchedBorder());
top.add(mode);
top.add(clear);
mid.add(new JLabel("Lead:")); mid.add(leadLabel);
mid.add(new JLabel("Anchor:")); mid.add(anchorLabel);
mid.add(new JLabel("Minimum:")); mid.add(minLabel);
mid.add(new JLabel("Maximum:")); mid.add(maxLabel);
add(top);
add(mid);
add(bottom);
mode.addItem(single);
mode.addItem(singleInterval);
mode.addItem(multipleInterval);
initializeSelectionMode();
bottom.add(new JLabel("Selected Indices:"));
bottom.add(selIndicesLabel);
mode.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if(e.getStateChange() == ItemEvent.SELECTED)
setSelectionMode((String)e.getItem());
clear.addActionListener(new ActionListener() {
list.clearSelection();
public void update() {
int lead = list.getLeadSelectionIndex(),
min = list.getMinSelectionIndex(),
max = list.getMaxSelectionIndex(),
anchor = list.getAnchorSelectionIndex();
leadLabel.setText(Integer.toString(lead) + " / ");
anchorLabel.setText(Integer.toString(anchor) + " / ");
minLabel.setText(Integer.toString(min) + " / ");
maxLabel.setText(Integer.toString(max) + " / ");
String s = new String();
for(int i = 0; i < selected.length; ++i) {
s += Integer.toString(selected[i]);
if(i < selected.length-1)
s += ",";
selIndicesLabel.setText(s);
validate();
private void initializeSelectionMode() {
int m = list.getSelectionMode();
switch(m) {
case ListSelectionModel.SINGLE_SELECTION:
mode.setSelectedItem(single);
break;
case ListSelectionModel.SINGLE_INTERVAL_SELECTION:
mode.setSelectedItem(singleInterval);
case ListSelectionModel.MULTIPLE_INTERVAL_SELECTION:
mode.setSelectedItem(multipleInterval);
private void setSelectionMode(String s) {
if(s.equals("SINGLE_SELECTION")) {
list.setSelectionMode(
ListSelectionModel.SINGLE_SELECTION);
else if(s.equals("SINGLE_INTERVAL_SELECTION")) {
ListSelectionModel.SINGLE_INTERVAL_SELECTION);
else if(s.equals("MULTIPLE_INTERVAL_SELECTION")) {
ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
例17-6 處理清單資料事件
private String[] items = {
"item one", "item two", "item three",
"item nine", "item ten"
JPanel controlPanel = new ControlPanel(this, list);
final DefaultListModel model = new DefaultListModel();
if(list.isShowing())
list.revalidate();
model.addListDataListener(new ListDataListener() {
public void contentsChanged(ListDataEvent e) {
showStatus("contents changed");
public void intervalRemoved(ListDataEvent e) {
Object[] message = new Object[] {
"Removed item at index " + e.getIndex0(),
" ",
"There are now " + model.getSize() + " items"
JOptionPane.showMessageDialog(Test.this,
message,
"Items Removed", // title
JOptionPane.INFORMATION_MESSAGE); // type
public void intervalAdded(ListDataEvent e) {
showStatus("interval added");
JButton repopulate = new JButton("repopulate");
public ControlPanel(final Test applet, final JList list) {
add(repopulate);
repopulate.addActionListener(new ActionListener() {
applet.populateList();
例17-7 處理滑鼠輕按兩下和三擊
String[] items = { "item one", "item two", "item three",
list.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
JList theList = (JList)e.getSource();
ListModel model = theList.getModel();
int index = theList.locationToIndex(e.getPoint());
String itemString =
(String)model.getElementAt(index);
String s = new String(" for " +
model.getElementAt(index));
switch(e.getClickCount()) {
case 1:
showStatus("Single Click" + s);
case 2:
showStatus("Double Click" + s);
case 3:
showStatus("Triple Click" + s);
17.3.3 JList類總結
17.3.4 AWT相容
17.4 本章回顧
略