分享
 
 
 

制作更酷的JList界面

王朝java/jsp·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

内容:

1。绘制器的工作原理。

2。用自订的绘制器更换JList和JComboBox的外观。

3。让新的外观响应鼠标事件。

借助swing体系的mvc设计理念,为组件更换不同的外观成为轻而易举的事情。本文主要以JList和JComboBox为例讲解ListCellRenderer的原理与用法.

一、绘制器的工作原理

不管是JList还是JComboBox,它们都用到了ListCellRenderer,因为JComboBox本身就是由一个下拉式的JList和TextField组成的. 在这里,它们使用了callback的机制。

callback的一是种常见的方式是在A类中调用B类中的方法,在A类中先要登记一个(也可以是多个)B类的实例引用,在需要调用时再通过该实例来调用它的内部方法.这样的机制在很多的设计模式中都有用到,如Observer等.还有AWT的事件机制也用到了callback.

要实现callback,通常将B类设计成一个能被callback的接口.在JList的绘制器中,swing提供了一个ListCellRenderer接口,

public interface ListCellRenderer {

Component getListCellRendererComponent(

JList list,

Object value,

int index,

boolean isSelected,

boolean cellHasFocus);

}

这个接口只提供一个方法,我们只要实现了这个接口,并将它的实例引用传给JList,就可以将JList替换成不同的样式了.看一下ListCellRenderer是如何工作的,

在绘制JList的每个Cell之前,它会去调用getListCellComponent( ),得到一个Component,并

将这个Component绘制在正确的位置.因为getListCellComponent( )返回的是Component,所以我们几乎可以扩展任意一个Component,来改变JList,JComboBox等的外观.

二、制作自已的绘制器

我们现在要想让JList中显示一组学生名单,同时每个名单前显示该学生的图标.如下图所示

我们先来想一想,Swing中有什么组件既可以显示图标也可以显示文字? JLabel.对了。我们就用JLabel作为JList的绘制器,看看我扩展的JLabel类,它实现了ListCellRenderer接口:

/* 可以显示图标的ListCell绘制器 */

public class IconListItemRenderer extends JLabel implements ListCellRenderer

{

private Border

selectedBorder = BorderFactory.createLineBorder(Color.blue,1),

emptyBorder = BorderFactory.createEmptyBorder(1,1,1,1);

public Component getListCellRendererComponent(

JList list,

Object value,

int index,

boolean isSelected,

boolean cellHasFocus)

{

IconListItem item = (IconListItem)value;

this.setIcon(item.getIcon());

this.setText(item.getText());

if ( isSelected ) setBorder (selectedBorder);

else setBorder(emptyBorder);

return this;

}

}

大家看到,getListCellRendererComponent方法会传入几个参数,我们就用它传入的几个参数设置JLabel的外观:图标与文字。在这个类中,我们用一个IconListItem接收调用者传过来的value,

IconListItem item = (IconListItem) value;

IconListItem是我另外定义好的一个类,它用来存放每一个List Item的值,

import javax.swing.*;

public class IconListItem

{

Icon icon;

String text;

public IconListItem(Icon icon, String text)

{

this.icon = icon;

this.text = text;

}

public Icon getIcon() { return icon;}

public String getText() { return text;}

public void setIcon(Icon icon){ this.icon = icon;}

public void setText(String text){ this.text = text; }

}

这样的话,我就可以用getIcon()和getText()方法取得每个List Item的值了,

IconListItem item = (IconListItem) value;

this.setIcon(item.getIcon());

this.setText(item.getText());

至此,我们就可以用以下方法方便的更换JList的外观了,

JList list = new JList();

list.setCellRenderer(new IconListItemRenderer()); file://安装我们自订的cellRenderer

DefaultListModel listModel = new DefaultListModel();

list.setModel(listModel);

IconListItem item = new IconListItem(new ImageIcon(...),"John");

listModel.addElement(item); // 为List增加Item

...

由于JComboBox也有一个下拉式清单,所以它的清单也是用ListCellRenderer来绘制的,所以我们也可以将这个IconListItemRenderer给它用:

JComboBox list = new JComboBox();

list.setRenderer(new IconListItemRenderer()); //装我们自订的cellRenderer

DefaultComboBoxModel comboModel = new DefaultComboBoxModel();

list.setModel(comboModel);

IconListItem item = new IconListItem(new ImageIcon(...),"John");

comboModel.addElement(item); // 为List增加Item

...

注意,JComboBox安装绘制器时是用setRenderer()方法,JList是用setCellRenderer()方法,名字稍有不同.

以上大家看到的是可显示一个图标的List, 下面我们再看一个可显示CheckBox的List是如何实现的,以下是例图:

代码实现:

import javax.swing.*;

import java.awt.*;

import javax.swing.border.*;

import java.awt.event.*;

/* 可以显示CheckBox的ListCell绘制器 */

public class CheckListItemRenderer extends JCheckBox implements ListCellRenderer

{

public Component getListCellRendererComponent(

JList list,

Object value,

int index,

boolean isSelected,

boolean cellHasFocus)

{

CheckListItem item = (CheckListItem)value;

this.setSelected(item.getCheck());

this.setText(item.getText());

this.setFont(list.getFont());

this.setEnabled(list.isEnabled());

return this;

}

}

同样这个绘制器中用一个CheckListItem存放每个List Item的值:

public class CheckListItem

{

boolean check;

String text;

public CheckListItem(boolean check, String text)

{

this.check = check;

this.text = text;

}

public boolean getCheck() { return check; }

public void setCheck(boolean _check) { check = _check; }

public String getText() { return text; }

public void setText(String _text) { text = _text; }

}

这个绘制器的用法同IconListItemRenderer一样,不多讲了.

三、让自订的绘制器响就鼠标事件

使用以上的CheckListItemRenderer时,大家会发现,虽然List中可以显示CheckBox了,但是用鼠标点击时,没有反应! 现在我就来解决这个问题.要澄清的是,ListCellRenderer本身是只返回一个组件用来绘制一个单元格,不能对用户动作作出反应。为些我们必须在JList上下功夫.JList有一个addMouseListener()方法可以为自身安装一个鼠标监听器,在这里,我实现了一个MouseAdapter,并让它对mousePressed作出响应:

class CheckListMouseListener extends MouseAdapter

{

public void mousePressed(MouseEvent e) {

JList list = (JList) e.getSource();

int index = list.locationToIndex(e.getPoint());

CheckListItem item = (CheckListItem)list.getModel().getElementAt(index);

item.setCheck(! item.getCheck());

Rectangle rect = list.getCellBounds(index, index);

list.repaint(rect);

}

}

使用时, 用addMouseListener(new CheckListMouseListener())就行了.

除了包含CheckBox的JList外,许多情况下,我们需要为自制的绘制器加上动作响应,如我们要实现一个可编辑的JList,除了要扩展JTextField及实现ListCellRenderer之外,还要写一个鼠标监听器和键盘监听器,当双击时,JList变成可编辑状态,当回车时,还原成不可编辑状态.具体的实现过程,我就不详叙了,留给大家作练习.

上面内容,我写了一个演示程序,下面是它的演示画面,

你可以从这里下载完整的演示程序.

以上文章为Turbo Chen原作,版权所有。如需转载,请注明来源.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有