一个很棒的答案是这个CheckBoxList
。它实现了Telcontar的答案(尽管早了三年 :) ...我在Java 1.6中使用它没有问题。我还添加了一个addCheckbox
方法,像这样(肯定可以更短,好久没用Java了):
public void addCheckbox(JCheckBox checkBox) {
ListModel currentList = this.getModel();
JCheckBox[] newList = new JCheckBox[currentList.getSize() + 1];
for (int i = 0; i < currentList.getSize(); i++) {
newList[i] = (JCheckBox) currentList.getElementAt(i);
}
newList[newList.length - 1] = checkBox;
setListData(newList);
}
我试用了Jidesoft的演示,玩弄CheckBoxList
时遇到了一些问题(一些不起作用的行为)。如果我发现我链接的CheckBoxList
也存在问题,我会修改这个答案。
创建一个自定义的ListCellRenderer
并将其分配给JList
。
在getListCellRendererComponent(...)
方法的实现中,这个自定义的ListCellRenderer
必须返回一个JCheckbox
。
但是这个JCheckbox
是不可编辑的,在屏幕上只是简单的绘制。你可以选择何时将此JCheckbox
打勾或取消勾选。
例如,当行被选中时(参数isSelected
),显示它被勾选,但这样做会导致检查状态在选择更改时不会保持不变。最好根据ListModel
下面的数据来显示已选择的项,然后由您来实现更改数据的选中状态的方法,并通知JList
重新绘制以更新状态。
如果需要,我稍后会发布示例代码。
只需实现一个ListCellRenderer
即可
public class CheckboxListCellRenderer extends JCheckBox implements ListCellRenderer {
public Component getListCellRendererComponent(JList list, Object value, int index,
boolean isSelected, boolean cellHasFocus) {
setComponentOrientation(list.getComponentOrientation());
setFont(list.getFont());
setBackground(list.getBackground());
setForeground(list.getForeground());
setSelected(isSelected);
setEnabled(list.isEnabled());
setText(value == null ? "" : value.toString());
return this;
}
}
并设置渲染器
JList list = new JList();
list.setCellRenderer(new CheckboxListCellRenderer());
这将导致:
附:如果您想要单选框,请将extends JCheckbox
替换为extends JRadioButton
。
我可能会使用 JTable 而不是 JList,由于复选框的默认渲染方式相当丑陋,我可能会想要添加一个自定义的 TableModel、CellRenderer 和 CellEditor 来表示布尔值。当然,我想象中这已经做了无数次了。Sun 公司提供了很好的示例。
我看到了这个问题并意识到一些答案已经过时了。现在,JList是通用的,因此有更好的解决方案。
我的通用JCheckBoxList解决方案:
import java.awt.Component;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.event.*;
@SuppressWarnings("serial")
public class JCheckBoxList extends JList<JCheckBox> {
protected static Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);
public JCheckBoxList() {
setCellRenderer(new CellRenderer());
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
int index = locationToIndex(e.getPoint());
if (index != -1) {
JCheckBox checkbox = (JCheckBox) getModel().getElementAt(index);
checkbox.setSelected(!checkbox.isSelected());
repaint();
}
}
});
setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
}
public JCheckBoxList(ListModel<JCheckBox> model){
this();
setModel(model);
}
protected class CellRenderer implements ListCellRenderer<JCheckBox> {
public Component getListCellRendererComponent(
JList<? extends JCheckBox> list, JCheckBox value, int index,
boolean isSelected, boolean cellHasFocus) {
JCheckBox checkbox = value;
//Drawing checkbox, change the appearance here
checkbox.setBackground(isSelected ? getSelectionBackground()
: getBackground());
checkbox.setForeground(isSelected ? getSelectionForeground()
: getForeground());
checkbox.setEnabled(isEnabled());
checkbox.setFont(getFont());
checkbox.setFocusPainted(false);
checkbox.setBorderPainted(true);
checkbox.setBorder(isSelected ? UIManager
.getBorder("List.focusCellHighlightBorder") : noFocusBorder);
return checkbox;
}
}
}
DefaultListModel<JCheckBox> model = new DefaultListModel<JCheckBox>();
JCheckBoxList checkBoxList = new JCheckBoxList(model);
DefaultListModel是通用的,因此您可以使用JAVA 7 API这里指定的方法,例如:
model.addElement(new JCheckBox("Checkbox1"));
model.addElement(new JCheckBox("Checkbox2"));
model.addElement(new JCheckBox("Checkbox3"));
我建议你使用一个一列的GridLayout JPanel。将复选框添加到JPanel中,并将JPanel设置为JScrollPane的数据源。要获取所选的CheckBoxes,只需调用getComponents()方法来获取JPanel中的CheckBoxes。
import java.awt.Component;
import javax.swing.JCheckBox;
import javax.swing.JList;
import javax.swing.ListCellRenderer;
class CheckListRenderer extends JCheckBox implements ListCellRenderer<Entity> {
@Override
public Component getListCellRendererComponent(JList<? extends Entity> list,
Entity value, int index, boolean isSelected, boolean cellHasFocus) {
setEnabled(list.isEnabled());
setSelected(value.isActive()); // sets the checkbox
setFont(list.getFont());
if (isSelected) { // highlights the currently selected entry
setBackground(list.getSelectionBackground());
setForeground(list.getSelectionForeground());
} else {
setBackground(list.getBackground());
setForeground(list.getForeground());
}
setText(value.toString()+" - A" + value.isActive()+" - F"+cellHasFocus+" - S"+isSelected );
return this;
}
}
public class Entity {
private boolean active = true;
public boolean isActive() {
return active;
}
public void setActive(boolean isActive) {
this.active = isActive;
}
}
list = new JList<Entity>();
list.setModel(new DefaultListModel<Entity>());
list.setCellRenderer(new CheckListRenderer());
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent event) {
if (event.getX() < 20) {
// Quick and dirty: only change the tick if clicked into the leftmost pixels
@SuppressWarnings("unchecked")
JList<Entity> list = ((JList<Entity>) event.getSource());
int index = list.locationToIndex(event.getPoint());// Get index of item clicked
if (index >= 0) {
Entity item = (Entity) list.getModel().getElementAt(index);
item.setActive(!item.isActive()); // Toggle selected state
list.repaint(list.getCellBounds(index, index));// Repaint cell
}
}
}
});
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
public class CheckBoxList extends JList
{
protected static Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);
public CheckBoxList()
{
setCellRenderer(new CellRenderer());
addMouseListener(new MouseAdapter()
{
public void mousePressed(MouseEvent e)
{
int index = locationToIndex(e.getPoint());
if (index != -1) {
JCheckBox checkbox = (JCheckBox)
getModel().getElementAt(index);
checkbox.setSelected(
!checkbox.isSelected());
repaint();
}
}
}
);
setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
}
protected class CellRenderer implements ListCellRenderer
{
public Component getListCellRendererComponent(
JList list, Object value, int index,
boolean isSelected, boolean cellHasFocus)
{
JCheckBox checkbox = (JCheckBox) value;
checkbox.setBackground(isSelected ?
getSelectionBackground() : getBackground());
checkbox.setForeground(isSelected ?
getSelectionForeground() : getForeground());
checkbox.setEnabled(isEnabled());
checkbox.setFont(getFont());
checkbox.setFocusPainted(false);
checkbox.setBorderPainted(true);
checkbox.setBorder(isSelected ?
UIManager.getBorder(
"List.focusCellHighlightBorder") : noFocusBorder);
return checkbox;
}
}
}
这是使用复选框制作列表的又一个示例。
class JCheckList<T> extends JList<T> {
protected static Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);
public void setSelected(int index) {
if (index != -1) {
JCheckBox checkbox = (JCheckBox) getModel().getElementAt(index);
checkbox.setSelected(
!checkbox.isSelected());
repaint();
}
}
protected static class CellListener
extends DefaultListModel
implements ListDataListener {
ListModel ls;
public CellListener(ListModel ls) {
ls.addListDataListener(this);
int i = ls.getSize();
for (int v = 0; v < i; v++) {
var r = new JCheckBox();
r.setText(ls.getElementAt(v).toString());
this.addElement(r);
}
this.ls = ls;
}
@Override
public void intervalAdded(ListDataEvent e) {
int begin = e.getIndex0();
int end = e.getIndex1();
for (; begin <= end; begin++) {
var r = new JCheckBox();
r.setText(ls.getElementAt(begin).toString());
this.add(begin, r);
}
}
@Override
public void intervalRemoved(ListDataEvent e) {
int begin = e.getIndex0();
int end = e.getIndex1();
for (; begin <= end; end--) {
this.remove(begin);
}
}
@Override
public void contentsChanged(ListDataEvent e) {
}
}
public JCheckList() {
setCellRenderer(new CellRenderer());
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
int index = locationToIndex(e.getPoint());
setSelected(index);
}
}
);
addKeyListener(new KeyListener(){
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_SPACE){
int index = JCheckList.this.getSelectedIndex();
setSelected(index);
}
}
@Override
public void keyReleased(KeyEvent e) {
}
});
setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
}
@Override
public void setModel(ListModel<T> d) {
var r = new CellListener(d);
d.addListDataListener(r);
super.setModel(r);
}
protected class CellRenderer implements ListCellRenderer {
public Component getListCellRendererComponent(
JList list, Object value, int index,
boolean isSelected, boolean cellHasFocus) {
JCheckBox checkbox = (JCheckBox) value;
checkbox.setBackground(isSelected
? getSelectionBackground() : getBackground());
checkbox.setForeground(isSelected
? getSelectionForeground() : getForeground());
checkbox.setEnabled(isEnabled());
checkbox.setFont(getFont());
checkbox.setFocusPainted(false);
checkbox.setBorderPainted(true);
checkbox.setBorder(isSelected
? UIManager.getBorder(
"List.focusCellHighlightBorder") : noFocusBorder);
return checkbox;
}
}
}