如何在 Java Swing 中制作带有复选框的列表?
题
在 Java Swing 中拥有每个项目都带有复选框的列表的最佳方式是什么?
IE。一个 JList,其中每个项目都有一些文本和一个复选框?
解决方案
创建自定义 ListCellRenderer
并将其分配给 JList
.
这个习俗 ListCellRenderer
必须返回一个 JCheckbox
在实施中 getListCellRendererComponent(...)
方法。
但是这个 JCheckbox
不可编辑,是在屏幕上进行简单的绘制,由您选择 JCheckbox
必须“勾选”或不勾选,
例如,当选择该行时显示它已打勾(参数 isSelected
),但这样如果选择更改,检查状态将不会保留。最好显示它已检查,查阅下面的数据 ListModel
, ,但是接下来由您来实现更改数据检查状态的方法,并将更改通知给 JList
重新粉刷。
如果您需要的话,我稍后会发布示例代码
其他提示
一个精彩的答案是这样的 CheckBoxList
. 。它实现了 Telcontar 的答案(尽管是 3 年前:)...我在 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
我链接到。
我可能会寻找使用 J表 而不是一个 列表 由于复选框的默认渲染相当难看,我可能希望添加一个自定义的 表模型, 细胞渲染器 和 单元格编辑器 来表示一个布尔值。当然,我想这已经被做过无数次了。太阳有 好例子.
只需实施一个 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());
这将导致
详情请见 自定义 Swing 组件渲染器.
附:如果你想要无线电元素只需替换 extends JCheckbox
和 extends JRadioButton
.
适用于 Java 7 及更高版本的更好解决方案
我偶然发现了这个问题,并意识到有些答案相当陈旧且过时。如今,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;
}
}
}
要动态添加 JCheckBox 列表,您需要创建自己的 ListModel 或添加 DefaultListModel。
DefaultListModel<JCheckBox> model = new DefaultListModel<JCheckBox>();
JCheckBoxList checkBoxList = new JCheckBoxList(model);
这 默认列表模型 是通用的,因此您可以使用 JAVA 7 API 指定的方法 这里 像这样:
model.addElement(new JCheckBox("Checkbox1"));
model.addElement(new JCheckBox("Checkbox2"));
model.addElement(new JCheckBox("Checkbox3"));
使用 Java,很有可能有人已经实现了您需要的小部件或实用程序。大型 OSS 社区的部分好处。除非您真的想自己动手,否则无需重新发明轮子。在这种情况下,这将是一次很好的 CellRenderers 和 Editor 学习练习。
我的项目在JIDE的帮助下取得了巨大的成功。您想要的组件(复选框列表)位于 JIDE 公共层(它是 OSS,托管在 java.net 上)。商业的东西也很好,但你不需要它。
http://www.jidesoft.com/products/oss.htm https://jide-oss.dev.java.net/
我建议您使用 GridLayout 为 1 列的 JPanel。将复选框添加到 JPanel 中,并将 JPanel 设置为 JScrollPane 的数据源。要获取选中的复选框,只需调用 JPanel 的 getComponents() 即可获取复选框。
这里只是 Rawa 对 JCheckBoxList 的一点补充。这将添加使用空格键进行选择的功能。如果选择了多个项目,则所有项目都将设置为第一个项目的反转值。
addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
int index = getSelectedIndex();
if (index != -1 && e.getKeyCode() == KeyEvent.VK_SPACE) {
boolean newVal = !((JCheckBox) (getModel()
.getElementAt(index))).isSelected();
for (int i : getSelectedIndices()) {
JCheckBox checkbox = (JCheckBox) getModel()
.getElementAt(i);
checkbox.setSelected(newVal);
repaint();
}
}
}
});
Swing 中的所有聚合组件(即由其他组件组成的组件,例如 JTable、JTree 或 JComboBox)都可以高度自定义。例如,JTable 组件通常显示 JLabel 组件的网格,但它也可以显示 JButton、JTextField 甚至其他 JTable。然而,让这些聚合组件显示非默认对象是比较容易的部分。使它们对键盘和鼠标事件做出正确的响应是一项更加困难的任务,这是因为将组件分离为“渲染器”和“编辑器”。这种分离(我认为)是一个糟糕的设计选择,并且在试图扩展摇摆组件时只会使事情变得复杂。
要明白我的意思,请尝试增强 Swing 的 JList 组件,以便它显示复选框而不是标签。根据 Swing 哲学,此任务需要实现两个接口:ListCellRenderer(用于绘制复选框)和 CellEditor(用于处理复选框上的键盘和鼠标事件)。实现 ListCellRenderer 接口很容易,但 CellEditor 接口可能相当笨拙且难以理解。在这种特殊情况下,我建议完全忘记 CellEditor 并直接处理输入事件,如以下代码所示。
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;
}
}
}
在这里,我拦截列表框中的鼠标单击并模拟相应复选框的单击。结果是一个“CheckBoxList”组件,它比使用 CellEditor 界面的等效组件更简单、更小。要使用该类,只需实例化它,然后通过调用 setListData 向其传递 JCheckBox 对象(或 JCheckBox 对象的子类)的数组。请注意,该组件中的复选框不会响应按键(即空格键),但如果需要,您可以随时添加自己的按键侦听器。
来源: DevX.com