第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 一个带有缺省列表模型的列表
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class Test extends JApplet {
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]" };
public void init() {
Container contentPane = getContentPane();
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() {
public void actionPerformed(ActionEvent e) {
final DefaultListModel model =
(DefaultListModel)list.getModel();
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 java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class Test extends JApplet {
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"
};
public void init() {
Container contentPane = getContentPane();
ListModel model =
new NameAndPictureListModel(names, pics);
ListCellRenderer renderer =
new NameAndPictureListCellRenderer();
JList list = new JList(model);
list.setCellRenderer(renderer);
list.setVisibleRowCount(5);
contentPane.setLayout(new FlowLayout());
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) {
Object[] array = (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 检测列表选取的调整值
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
public class Test extends JApplet {
public void init() {
Container contentPane = getContentPane();
String[] items = { "item[0]", "item[1]", "item[2]",
"item[3]", "item[4]", "item[5]",
"item[6]", "item[7]",
"item[8]", "item[9]" };
JList list = new JList(items);
contentPane.add(new JScrollPane(list),
BorderLayout.CENTER);
list.addListSelectionListener(
new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
String s;
if(e.getValueIsAdjusting()) {
s = "adjusting selection ...";
}
else {
s = "selection from " + e.getFirstIndex() +
" to " + e.getLastIndex();
}
showStatus(s);
}
});
}
}
例17-5 处理列表选取事件
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class Test extends JApplet {
private ControlPanel controlPanel;
public void init() {
Container contentPane = getContentPane();
JPanel listPanel = new JPanel();
String[] items = { "item[0]", "item[1]", "item[2]",
"item[3]", "item[4]", "item[5]",
"item[6]", "item[7]",
"item[8]", "item[9]" };
JList list = new JList(items);
list.setPrototypeCellValue("MMMMMMM");
controlPanel = new ControlPanel(list);
controlPanel.update();
listPanel.setBorder(BorderFactory.createEtchedBorder());
listPanel.add(new JScrollPane(list));
contentPane.add(controlPanel, BorderLayout.NORTH);
contentPane.add(listPanel, BorderLayout.CENTER);
list.addListSelectionListener(
new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
controlPanel.update();
}
});
}
}
class ControlPanel extends JPanel {
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() {
public void actionPerformed(ActionEvent e) {
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) + " / ");
int[] selected = list.getSelectedIndices();
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);
break;
case ListSelectionModel.MULTIPLE_INTERVAL_SELECTION:
mode.setSelectedItem(multipleInterval);
break;
}
}
private void setSelectionMode(String s) {
if(s.equals("SINGLE_SELECTION")) {
list.setSelectionMode(
ListSelectionModel.SINGLE_SELECTION);
}
else if(s.equals("SINGLE_INTERVAL_SELECTION")) {
list.setSelectionMode(
ListSelectionModel.SINGLE_INTERVAL_SELECTION);
}
else if(s.equals("MULTIPLE_INTERVAL_SELECTION")) {
list.setSelectionMode(
ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
}
}
}
例17-6 处理列表数据事件
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class Test extends JApplet {
private JList list = new JList();
private String[] items = {
"item one", "item two", "item three",
"item four", "item five", "item six",
"item seven", "item eight",
"item nine", "item ten"
};
public void init() {
Container contentPane = getContentPane();
JPanel controlPanel = new ControlPanel(this, list);
contentPane.add(controlPanel, BorderLayout.NORTH);
contentPane.add(new JScrollPane(list),
BorderLayout.CENTER);
populateList();
}
public void populateList() {
final DefaultListModel model = new DefaultListModel();
for(int i=0; i < items.length; ++i)
model.addElement(items[i]);
list.setModel(model);
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");
}
});
}
}
class ControlPanel extends JPanel {
JButton remove = new JButton("remove selected items");
JButton repopulate = new JButton("repopulate");
public ControlPanel(final Test applet, final JList list) {
add(remove);
add(repopulate);
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);
}
}
});
repopulate.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
applet.populateList();
}
});
}
}
例17-7 处理鼠标双击和三击
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class Test extends JApplet {
public void init() {
Container contentPane = getContentPane();
String[] 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);
contentPane.setLayout(new FlowLayout());
contentPane.add(new JScrollPane(list));
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);
break;
case 2:
showStatus("Double Click" + s);
break;
case 3:
showStatus("Triple Click" + s);
break;
}
}
});
}
}
17.3.3 JList类总结
17.3.4 AWT兼容
17.4 本章回顾
略