JComboBox是Java的Swing开发中比较常用的组件,但是默认的功能比较简单,在开发一个自己的小工具的时候,就希望能够通过上下方向键控制下拉框里Item的选中与否,并且希望能通过按Delete键对选中的Item进行删除,但是JComboBox从设计上就禁掉了对下来框里Item的各种事件的操作,所以实现起来就要换个思路,不能对下拉框里的Item进行绑定事件,因为他无法获取焦点,而焦点一直在JCombox的文本框里(我设置的是可编辑的JCombox),所以应该把事件加到JCombox的编辑框中,通过编辑框的KeyListener事件进行监听,代码如下:
package javax.swing;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
/**
*
* 带键盘事件的渲染器
*
* @author 倪庆洋 <niqy@qq.com>
*
* @date 2015-1-17 下午05:34:02
*
*/
public class LabelCellRenderer extends JLabel implements ListCellRenderer, KeyListener {
private static final long serialVersionUID = 1L;
private JComboBox comboBox;
private int selectedIndex = -1;
/**
* 构造函数
*
* @param comboBox
* 当前渲染器所属的JComboBox
*/
public LabelCellRenderer(final JComboBox comboBox) {
setOpaque(true);
this.comboBox = comboBox;
this.comboBox.getEditor().getEditorComponent().addKeyListener(this);
}
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
this.setText(value.toString());
this.setFont(this.comboBox.getFont());
Color background;
Color foreground;
if (isSelected) {
background = Color.decode("#3399FE");
foreground = Color.WHITE;
this.selectedIndex = index;
} else {
background = Color.WHITE;
foreground = Color.BLACK;
}
setBackground(background);
setForeground(foreground);
return this;
}
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == 38) {// 按向上的方向键则索引减一
int index = this.comboBox.getSelectedIndex();
if (index == 0) {
return;
}
index--;
this.comboBox.setSelectedIndex(index);
} else if (keyCode == 40) {// 按向下的方向键则索引加一
int index = this.comboBox.getSelectedIndex();
if (index == this.comboBox.getItemCount() - 1) {
return;
}
index++;
this.comboBox.setSelectedIndex(index);
}else if(keyCode == 127){
// 为防止误删除,只有在下来选项可视的情况下才可以执行删除操作
if (this.comboBox.isPopupVisible()) {
// 下来选框可见的情况下,设置Delete对文本框内文字操作无效
JTextField textField = ((JTextField) this.comboBox.getEditor().getEditorComponent());
String text = textField.getText();
int position = ((JTextField) this.comboBox.getEditor().getEditorComponent()).getCaretPosition();
// 如果是按Delete键则移除当前选中的Item
if (this.selectedIndex >= 0 && this.selectedIndex < this.comboBox.getItemCount()) {
this.comboBox.removeItemAt(this.selectedIndex);
textField.setText(text);
textField.setCaretPosition(position);
}
//此处代码在JDK1.6起作用,在JDK1.7失效,请注意
e.setKeyCode(-1);
}
}
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
}
}
通过此渲染器对Item进行重新渲染,在渲染的过程中记录所选择的索引并进行键盘事件的监听。
调用如下:
package com.cntrust.file.test;
import javax.swing.JComboBox;
import javax.swing.JFrame;
//自定义
import javax.swing.LabelCellRenderer;
public class TestMain {
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
JComboBox comboBox = new JComboBox();
//只有为true的时候才能进行删除
comboBox.setEditable(true);
comboBox.setRenderer(new LabelCellRenderer(comboBox));
JFrame jFrame = new JFrame();
jFrame.add(comboBox);
comboBox.addItem("张三");
comboBox.addItem("李四");
comboBox.addItem("王五");
comboBox.addItem("赵六");
jFrame.setSize(280, 60);
jFrame.setVisible(true);
}
}
效果如下图:
删除前:
删除后: