Java中广泛采用一种接口式的设计,这使得Java的Swing组件的表现上十分灵活。
Jlist究竟是如何设计的呢?事实上:Jlist把图形和数据进行的分离。JList中可以T可以是字符串数组。
String[] text={
A,B,C,D};
JList<String> list=new JList<String>(text);
如想要自由地添加列表元素,可以获得一个DefaultListModel,它实现了ListModel接口
DefaultListModel<String> model=new DefaultListModel<>();
使用addElement()就可以添加元素了,并且还会通知JList重新绘制列表。
改变JList的外观需要设置单元格渲染器,单元格渲染器需要继承JComponent并实现ListCellRenderer接口
每次绘制单元格时,就会调用public Component
getListCellRendererComponent(JList<? extends Object> list, Object value,
int index,boolean isSelected, boolean cellHasFocus)方法,并返回
Component对象,并使用paintComponent()方法绘制出单元格,绘制完成后,调用
getPreferredSize()返回组件的大小。
有一种简单的方法就是在public Component
getListCellRendererComponent(JList<? extends Object> list, Object value,
int index,boolean isSelected, boolean cellHasFocus)方法中创建JLabel对象并返回,这样就不要我们用画笔(Graphics对象)绘制了。这就相当于在列表中加入了标签。
JList是不带滚动条的,也需要我们自己去定制。
不得不承认,这十分复杂,但这样的设计可以使得我们自由的设置列表的样式。甚至对每一个单元格都可以定制它的样式。这用其他的语言实现恐怕会需要更多的代码。
下面给出一个例子
package JList;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import javax.swing.DefaultListModel;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListCellRenderer;
public class JListTest {
public static void main(String[] args)
{
AreaListFrame frame=new AreaListFrame("Area");
EventQueue.invokeLater(()->{
frame.setVisible(true);
});
}
}
class AreaListFrame extends JFrame
{
private JList<String> areaList;
public AreaListFrame(String title)
{
super(title);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout());
JPanel cpanel=new JPanel();
DefaultListModel<String> model=new DefaultListModel<>();
model.addElement("安徽");
model.addElement("湖南");
model.addElement("山东");
model.addElement("东北");
model.addElement("辽宁");
model.addElement("湖北");
model.addElement("河北");
model.addElement("河南");
model.addElement("江苏");
model.addElement("浙江");
model.addElement("新疆");
areaList=new JList<>(model);
areaList.setCellRenderer(new MyRenderer());
//后来加入元素,列表自动重新绘制
model.addElement("黑龙江");
cpanel.add(new JScrollPane(areaList),BorderLayout.CENTER);
add(cpanel);
pack();
}
class MyRenderer extends JComponent implements ListCellRenderer<String>
{
private Font font=new Font(Font.SANS_SERIF,Font.PLAIN,18);
private String text;
private int index;
private Color evenColor=Color.LIGHT_GRAY;
private Color oddColor=new Color(34, 134, 235);
private Color selectedColor=Color.RED;
private Color background;
@Override
public Component getListCellRendererComponent(JList<? extends String> list, String value, int index,
boolean isSelected, boolean cellHasFocus)
{
text=value;
list.setSelectionBackground(selectedColor);
this.index=index;
//根据是否选中得到动态的颜色
ibackground = isSelected ? selectedColor : index%2==0? evenColor:oddColor;
return this;
}
public void paintComponent(Graphics g)
{
FontMetrics fm=g.getFontMetrics(font);
g.setColor(background);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.GREEN);
g.drawString(text,0 ,fm.getAscent());
}
@Override
public Dimension getPreferredSize()
{
Graphics g=getGraphics();
FontMetrics fm=g.getFontMetrics(font);
return new Dimension(fm.stringWidth(text),fm.getHeight());
}
/*public Component getListCellRendererComponent(JList<? extends String> list, String value, int index,
boolean isSelected, boolean cellHasFocus)
{
JLabel j1=new JLabel(value);
j1.setOpaque(true);
evenColor=Color.LIGHT_GRAY;
oddColor=new Color(34, 134, 235);
if(index%2==0) j1.setBackground(evenColor);
else j1.setBackground(oddColor);
j1.setFont(new Font(Font.SANS_SERIF,Font.PLAIN,16));
if(isSelected) j1.setBackground(Color.YELLOW);
return j1 ;
}
*/
}
}