分享
 
 
 

Swing探索:编写一个JCheckListBox组件

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

记得Delphi里面有一个TCheckListBox控件,是一个可打勾的列表。现在我们也做一个,就叫JCheckListBox吧。

写代码之前,先考虑以下问题:

· 继承:当然是从Swing的JList继承。

· 数据扩充:对于JList来说,它是显示了一系列Object。无论其类型如何,都用一个默认的渲染器(DefaultListCellRenderer,从JLabel继承而来)来画,每个条目的文字用Object.toString()来设置。但是对于JCheckListBox来说,除了显示文本外,还要考虑每个条目是否被选中,如果选中,要显示“打勾”。所以,JList需要维护“每一个条目是否选中”的状态信息。我们放在一个boolean数组中。

· 渲染器:默认的Renderer肯定是不行了,无法显示打勾。自然想到用JCheckBox来重新做一个渲染器,设置到JCheckListBox中。

· 鼠标监听器:现在可以画每个条目了,但还不够,必须能响应鼠标的点击以便Check/UnCheck才行。所以要在JCheckListBox上加一个鼠标监听器来响应鼠标事件。当然,如果你想让它相应键盘输入(例如Ctrl+A全选)也可如法炮制。

· CheckListBoxModel:为了操作方便,这里还从AbstractListModel扩充一个CheckListBoxModel,它能在条目Check变化时发送事件。

好了,由于代码和原理都比较简单,不再赘述,直接给出代码,以及简单注释:

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import javax.swing.event.*;

public class JCheckListBox extends JList {

//这个boolean数组装载所有item是否被check的信息。

private boolean[] checkedItems = null;

/**

* 定义一个简单的ListModel,它可以发送check变化事件。

*/

class CheckListBoxModel extends AbstractListModel {

private Object[] items = null;

CheckListBoxModel(Object[] items) {

this.items = items;

}

public int getSize() {

return items.length;

}

public Object getElementAt(int i) {

return items[i];

}

protected void fireCheckChanged(Object source, int index) {

fireContentsChanged(source, index, index);

}

public Object getItem(int index) {

return items[index];

}

}

/**

* 这里就覆盖了一个构造函数。其他JList你自己覆盖吧,反正super一下再init就OK了。

* @param items Object[]

*/

public JCheckListBox(Object[] items) {

setModel(new CheckListBoxModel(items));

init();

}

/**

* 初始化控件。包括初始化boolean数组、安装一个渲染器、安装一个鼠标监听器。

*/

protected void init() {

checkedItems = new boolean[this.getModel().getSize()];

class MyCellRenderer extends JCheckBox implements ListCellRenderer {

public MyCellRenderer() {

setOpaque(true);

}

public Component getListCellRendererComponent(

JList list,

Object value,

int index,

boolean isSelected,

boolean cellHasFocus) {

//这点代码基本上从DefaultListCellRenderer.java中抄袭的。

setComponentOrientation(list.getComponentOrientation());

if (isSelected) {

setBackground(list.getSelectionBackground());

setForeground(list.getSelectionForeground());

} else {

setBackground(list.getBackground());

setForeground(list.getForeground());

}

if (value instanceof Icon) {

setIcon( (Icon) value);

setText("");

} else {

setIcon(null);

setText( (value == null) ? "" : value.toString());

}

setEnabled(list.isEnabled());

setFont(list.getFont());

//虽然抄袭,可这里别忘了设置check信息。

this.setSelected(isChecked(index));

return this;

}

}

this.setCellRenderer(new MyCellRenderer());

//定义一个鼠标监听器。如果点击某个item,翻转其check状态。

class CheckBoxListener extends MouseAdapter {

public void mouseClicked(MouseEvent e) {

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

invertChecked(index);

}

}

this.addMouseListener(new CheckBoxListener());

}

/**

* 翻转指定item的check状态。

* @param index int

*/

public void invertChecked(int index) {

checkedItems[index] = !checkedItems[index];

//别忘了发送event。

CheckListBoxModel model = (CheckListBoxModel) getModel();

model.fireCheckChanged(this, index);

this.repaint();

}

/**

* 是否指定item被check。

* @param index int

* @return boolean

*/

public boolean isChecked(int index) {

return checkedItems[index];

}

/**

* 获得选中的item个数

*/

public int getCheckedCount() {

int result = 0;

for (int i = 0; i < checkedItems.length; i++) {

if (checkedItems[i]) {

result++;

}

}

return result;

}

/**

* 所有选中item索引的数组。

*/

public int[] getCheckedIndices() {

int[] result = new int[getCheckedCount()];

int index = 0;

for (int i = 0; i < checkedItems.length; i++) {

if (checkedItems[i]) {

result[index] = i;

index++;

}

}

return result;

}

public static void main(String[] args) {

JFrame frame = new JFrame("JCheckListBox - xiaozhonghua@hotmail.com");

final JCheckListBox list = new JCheckListBox(new Object[] {"张三", "李四", "王二麻子", "木头六"});

frame.getContentPane().add(new JScrollPane(list), BorderLayout.CENTER);

JButton button = new JButton("OK");

button.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {

System.exit(0);

}

});

frame.getContentPane().add(button, BorderLayout.SOUTH);

final JLabel label = new JLabel("当前没有选择。");

list.getModel().addListDataListener(new ListDataListener() {

public void intervalAdded(ListDataEvent e) {}

public void intervalRemoved(ListDataEvent e) {}

public void contentsChanged(ListDataEvent e) {

if (list.getCheckedCount() == 0) {

label.setText("当前没有选择。");

} else {

String text = "当前选择:";

int[] indices = list.getCheckedIndices();

for (int i = 0; i < indices.length; i++) {

text += ( (CheckListBoxModel) list.getModel()).getItem(indices[i]).toString() + ",";

}

label.setText(text);

}

}

});

frame.getContentPane().add(label, BorderLayout.NORTH);

frame.setBounds(300, 300, 400, 200);

frame.show();

}

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
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- 王朝網路 版權所有