在 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());

这将导致

CheckboxListCellRenderer example

详情请见 自定义 Swing 组件渲染器.

附:如果你想要无线电元素只需替换 extends JCheckboxextends 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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top