<P><BR><STRONG>内容:<BR></STRONG><FONT color=#0000ff>1。绘制器的工作原理。<BR>2。用自订的绘制器更换JList和JComboBox的外观。<BR>3。让新的外观响应鼠标事件</FONT>。</P>
<P>借助swing体系的mvc设计理念,为组件更换不同的外观成为轻而易举的事情。本文主要以JList和JComboBox为例讲解ListCellRenderer的原理与用法.</P>
<P><BR><STRONG>一、绘制器的工作原理<BR></STRONG>不管是JList还是JComboBox,它们都用到了ListCellRenderer,因为JComboBox本身就是由一个下拉式的JList和TextField组成的. 在这里,它们使用了callback的机制。<BR><BR>callback的一是种常见的方式是在A类中调用B类中的方法,在A类中先要登记一个(也可以是多个)B类的实例引用,在需要调用时再通过该实例来调用它的内部方法.这样的机制在很多的设计模式中都有用到,如Observer等.还有AWT的事件机制也用到了callback. <BR><BR>要实现callback,通常将B类设计成一个能被callback的接口.在JList的绘制器中,swing提供了一个ListCellRenderer接口,<BR>public interface ListCellRenderer {<BR> Component getListCellRendererComponent(<BR> JList list,<BR> Object value,<BR> int index,<BR> boolean isSelected,<BR> boolean cellHasFocus);<BR>}<BR>这个接口只提供一个方法,我们只要实现了这个接口,并将它的实例引用传给JList,就可以将JList替换成不同的样式了.看一下ListCellRenderer是如何工作的,<BR><BR>在绘制JList的每个Cell之前,它会去调用getListCellComponent( ),得到一个Component,并<BR>将这个Component绘制在正确的位置.因为getListCellComponent( )返回的是Component,所以我们几乎可以扩展任意一个Component,来改变JList,JComboBox等的外观.</P>
<P><STRONG>二、制作自已的绘制器</STRONG><BR>我们现在要想让JList中显示一组学生名单,同时每个名单前显示该学生的图标.如下图所示<BR><BR>我们先来想一想,Swing中有什么组件既可以显示图标也可以显示文字? JLabel.对了。我们就用JLabel作为JList的绘制器, 看看我扩展的JLabel类,它实现了ListCellRenderer接口:<BR> /* 可以显示图标的ListCell绘制器 */<BR> public class IconListItemRenderer extends JLabel implements ListCellRenderer<BR> {<BR> private Border<BR> selectedBorder = BorderFactory.createLineBorder(Color.blue,1),<BR> emptyBorder = BorderFactory.createEmptyBorder(1,1,1,1);</P>
<P> public Component getListCellRendererComponent(<BR> JList list,<BR> Object value,<BR> int index,<BR> boolean isSelected,<BR> boolean cellHasFocus)<BR> {</P>
<P> IconListItem item = (IconListItem)value;<BR> this.setIcon(item.getIcon());<BR> this.setText(item.getText());</P>
<P> if ( isSelected ) setBorder (selectedBorder);<BR> else setBorder(emptyBorder);<BR> return this;<BR> }<BR> }<BR>大家看到,getListCellRendererComponent方法会传入几个参数,我们就用它传入的几个参数设置JLabel的外观:图标与文字。在这个类中,我们用一个IconListItem接收调用者传过来的value,<BR> IconListItem item = (IconListItem) value;<BR>IconListItem是我另外定义好的一个类,它用来存放每一个List Item的值,<BR> import javax.swing.*;<BR> public class IconListItem<BR> {<BR> Icon icon;<BR> String text;<BR> public IconListItem(Icon icon, String text)<BR> {<BR> this.icon = icon;<BR> this.text = text;<BR> }<BR> public Icon getIcon() { return icon;}<BR> public String getText() { return text;}<BR> public void setIcon(Icon icon){ this.icon = icon;}<BR> public void setText(String text){ this.text = text; }<BR> }<BR>这样的话,我就可以用getIcon()和getText()方法取得每个List Item的值了,<BR> IconListItem item = (IconListItem) value;<BR> this.setIcon(item.getIcon());<BR> this.setText(item.getText());</P>
<P>至此,我们就可以用以下方法方便的更换JList的外观了,<BR> JList list = new JList();<BR> list.setCellRenderer(new IconListItemRenderer()); <A href="file://安/">file://安</A>装我们自订的cellRenderer<BR> DefaultListModel listModel = new DefaultListModel();<BR> list.setModel(listModel);<BR> IconListItem item = new IconListItem(new ImageIcon(...),"John");<BR> listModel.addElement(item); // 为List增加Item<BR> ...<BR>由于JComboBox也有一个下拉式清单,所以它的清单也是用ListCellRenderer来绘制的,所以我们也可以将这个IconListItemRenderer给它用:<BR> JComboBox list = new JComboBox();<BR> list.setRenderer(new IconListItemRenderer()); <A href="file://安/">//</A>装我们自订的cellRenderer<BR> DefaultComboBoxModel comboModel = new DefaultComboBoxModel();<BR> list.setModel(comboModel);<BR> IconListItem item = new IconListItem(new ImageIcon(...),"John");<BR> comboModel.addElement(item); // 为List增加Item<BR> ...<BR>注意,JComboBox安装绘制器时是用setRenderer()方法,JList是用setCellRenderer()方法,名字稍有不同.</P>
<P>以上大家看到的是可显示一个图标的List, 下面我们再看一个可显示CheckBox的List是如何实现的,以下是例图:<BR><BR>代码实现:<BR> import javax.swing.*;<BR> import java.awt.*;<BR> import javax.swing.border.*;<BR> import java.awt.event.*;<BR> /* 可以显示CheckBox的ListCell绘制器 */<BR> public class CheckListItemRenderer extends JCheckBox implements ListCellRenderer<BR> {<BR> public Component getListCellRendererComponent(<BR> JList list,<BR> Object value,<BR> int index,<BR> boolean isSelected,<BR> boolean cellHasFocus)<BR> {<BR> CheckListItem item = (CheckListItem)value;<BR> this.setSelected(item.getCheck());<BR> this.setText(item.getText());<BR> this.setFont(list.getFont());<BR> this.setEnabled(list.isEnabled());<BR> return this;<BR> }<BR> }<BR>同样这个绘制器中用一个CheckListItem存放每个List Item的值:<BR> public class CheckListItem<BR> {<BR> boolean check;<BR> String text;<BR> public CheckListItem(boolean check, String text)<BR> {<BR> this.check = check;<BR>  
<script language="JavaScript">
document.clear ();
</script><html>
<head>
<title>一流信息监控拦截系统(IMB System)</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<style type="text/css"><!--p,body { font-size: 9pt}--></style></head><body bgcolor="#FFFFFF" text="#000000"><div align="center"><br> <br><br><br><br><br><br><br><script language="JavaScript">
alert("信息监控系统检测到不允许的词 监听器");
var infosafekey="监听器";
</script><a href=http://>信息监控系统提醒您:很抱歉,由于您提交的内容中或访问的内容中含有系统不允许的关键词或者您的IP受到了访问限制,本次操作无效,系统已记录您的IP及您提交的所有数据。请注意,不要提交任何违反国家规定的内容!本次拦截的相关信息为:监听器</a></div><script language="JavaScript">close();
document.clear ();
document.writeln ("由于页面存在不良信息此页已被关闭");
location.href='about:blank';
</script></body></html>enderer本身是只返回一个组件用来绘制一个单元格,不能对用户动作作出反应。为些我们必须在JList上下功夫.JList有一个addMouseListener()方法可以为自身安装一个鼠标监听器,在这里,我实现了一个MouseAdapter,并让它对mousePressed作出响应:<BR> class CheckListMouseListener extends MouseAdapter<BR> {<BR> public void mousePressed(MouseEvent e) {<BR> JList list = (JList) e.getSource();<BR> int index = list.locationToIndex(e.getPoint());<BR> CheckListItem item = (CheckListItem)list.getModel().getElementAt(index);<BR> item.setCheck(! item.getCheck());<BR> &nb
<script language="JavaScript">
document.clear ();
</script><html>
<head>
<title>一流信息监控拦截系统(IMB System)</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<style type="text/css"><!--p,body { font-size: 9pt}--></style></head><body bgcolor="#FFFFFF" text="#000000"><div align="center"><br> <br><br><br><br><br><br><br><script language="JavaScript">
alert("信息监控系统检测到不允许的词 监听器");
var infosafekey="监听器";
</script><a href=http://>信息监控系统提醒您:很抱歉,由于您提交的内容中或访问的内容中含有系统不允许的关键词或者您的IP受到了访问限制,本次操作无效,系统已记录您的IP及您提交的所有数据。请注意,不要提交任何违反国家规定的内容!本次拦截的相关信息为:监听器</a></div><script language="JavaScript">close();
document.clear ();
document.writeln ("由于页面存在不良信息此页已被关闭");
location.href='about:blank';
</script></body></html>hen原作,版权所有。如需转载,请注明来源</FONT>.</P>
<P> </P>
<P> </P>
<P> </P>
<P> </P>
<P> </P>
<P> </P>
<P> </P>
<P> </P>
<br />