如何在 Java Swing 中创建带有复选框的列表?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19766/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 07:13:11  来源:igfitidea点击:

How do I make a list with checkboxes in Java Swing?

javaswingjcheckbox

提问by Shabaz

What would be the best way to have a list of items with a checkbox each in Java Swing?

在 Java Swing 中拥有一个带有复选框的项目列表的最佳方法是什么?

I.e. a JList with items that have some text and a checkbox each?

即带有项目的 JList,每个项目都有一些文本和一个复选框?

采纳答案by Telcontar

Create a custom ListCellRendererand asign it to the JList.

创建自定义ListCellRenderer并将其分配给JList.

This custom ListCellRenderermust return a JCheckboxin the implementantion of getListCellRendererComponent(...)method.

此自定义ListCellRenderer必须JCheckboxgetListCellRendererComponent(...)方法的实现中返回 a 。

But this JCheckboxwill not be editable, is a simple paint in the screen is up to you to choose when this JCheckboxmust be 'ticked' or not,

但这JCheckbox将是不可编辑的,屏幕上的简单绘画是否由您选择何时JCheckbox必须“勾选”,

For example, show it ticked when the row is selected (parameter isSelected), but this way the check status will no be mantained if the selection changes. Its better to show it checked consulting the data below the ListModel, but then is up to you to implement the method who changes the check status of the data, and notify the change to the JListto be repainted.

例如,在选择行时显示它打勾(参数isSelected),但是如果选择更改,则不会保持检查状态。最好显示它检查参考下面的数据ListModel,但是由您实现更改数据检查状态的方法,并将更改通知JList给要重绘的。

I Will post sample code later if you need it

如果您需要,我稍后会发布示例代码

ListCellRenderer

列表单元渲染器

回答by ninesided

I'd probably be looking to use a JTablerather than a JListand since the default rendering of a checkbox is rather ugly, I'd probably be looking to drop in a custom TableModel, CellRendererand CellEditorto represent a boolean value. Of course, I would imagine this has been done a bajillion times already. Sun has good examples.

我可能希望使用JTable而不是JList并且由于复选框的默认呈现相当丑陋,我可能希望放入自定义TableModelCellRendererCellEditor来表示布尔值。当然,我想这已经完成了无数次。Sun 有很好的例子

回答by basszero

Odds are good w/ Java that someone has already implemented the widget or utility you need. Part of the benefits of a large OSS community. No need to reinvent the wheel unless you really want to do it yourself. In this case it would be a good learning exercise in CellRenderers and Editors.

使用 Java 的可能性很大,因为有人已经实现了您需要的小部件或实用程序。大型 OSS 社区的部分好处。除非你真的想自己做,否则不需要重新发明轮子。在这种情况下,这将是 CellRenderers 和 Editors 中的一个很好的学习练习。

My project has had great success with JIDE. The component you want, a Check Box List, is in the JIDE Common Layer (which is OSS and hosted on java.net). The commercial stuff is good too, but you don't need it.

我的项目在 JIDE 上取得了巨大的成功。您想要的组件,即复选框列表,位于 JIDE 公共层(它是 OSS 并托管在 java.net 上)中。商业的东西也很好,但你不需要它。

http://www.jidesoft.com/products/oss.htmhttps://jide-oss.dev.java.net/

http://www.jidesoft.com/products/oss.htm https://jide-oss.dev.java.net/

回答by Dan Rosenstark

A wonderful answer is this CheckBoxList. It implements Telcontar's answer (though 3 years before :)... I'm using it in Java 1.6 with no problems. I've also added an addCheckboxmethod like this (surely could be shorter, haven't used Java in a while):

这是一个很好的答案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);
}

I tried out the demo for the Jidesoft stuff, playing with the CheckBoxListI encountered some problems (behaviors that didn't work). I'll modify this answer if I find problems with the CheckBoxListI linked to.

我尝试了 Jidesoft 东西的演示,玩CheckBoxList我遇到了一些问题(不起作用的行为)。如果我发现CheckBoxListI 链接的问题,我会修改这个答案。

回答by Zero_8

I recommend you use a JPanel with a GridLayout of 1 column. Add the checkBoxes to the JPanel, and set the JPanel as the data source of a JScrollPane. And to get the selected CheckBoxes, just call the getComponents() of the JPanel to get the CheckBoxes.

我建议您使用 GridLayout 为 1 列的 JPanel。将复选框添加到 JPanel,并将 JPanel 设置为 JScrollPane 的数据源。要获取选中的复选框,只需调用 JPanel 的 getComponents() 即可获取复选框。

回答by Rawa

Better solution for Java 7 and newer

Java 7 及更新版本的更好解决方案

I stumbled upon this question and realized that some of the answers are pretty old and outdated. Nowadays, JList is generic and thus there are better solutions.

我偶然发现了这个问题,并意识到有些答案已经过时了。现在,JList 是通用的,因此有更好的解决方案。

My solution of the generic JCheckBoxList:

我对通用 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;
    }
  }
}

For dynamically adding JCheckBox lists you need to create your own ListModel or add the DefaultListModel.

要动态添加 JCheckBox 列表,您需要创建自己的 ListModel 或添加 DefaultListModel。

DefaultListModel<JCheckBox> model = new DefaultListModel<JCheckBox>();
JCheckBoxList checkBoxList = new JCheckBoxList(model);

The DefaultListModelare generic and thus you can use methods specified by JAVA 7 API herelike this:

DefaultListModel是通用的,因此你可以使用Java指定的7 API方法在这里是这样的:

model.addElement(new JCheckBox("Checkbox1"));
model.addElement(new JCheckBox("Checkbox2"));
model.addElement(new JCheckBox("Checkbox3"));

回答by ?eljko Vukovi?

Here is just a little addition to the JCheckBoxList by Rawa. This will add the ability to select using space bar. If multiple items are selected, all will be set to inverted value of the first item.

这里只是 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();
                }
            }
        }
        });

回答by René Link

Just implement a ListCellRenderer

只需执行一个 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;
    }
}

and set the renderer

并设置渲染器

JList list = new JList();
list.setCellRenderer(new CheckboxListCellRenderer());

this will result in

这将导致

CheckboxListCellRenderer example

CheckboxListCellRenderer 示例

Details at Custom swing component renderers.

自定义 Swing 组件渲染器的详细信息。

PS: If you want radio elements just replace extends JCheckboxwith extends JRadioButton.

PS:如果你想要无线电元素,只需替换extends JCheckboxextends JRadioButton.

回答by Lucky

All of the aggregate components in Swing--that is, components made up other components, such as JTable, JTree, or JComboBox--can be highly customized. For example, a JTable component normally displays a grid of JLabel components, but it can also display JButtons, JTextFields, or even other JTables. Getting these aggregate components to display non-default objects is the easy part, however. Making them respond properly to keyboard and mouse events is a much harder task, due to Swing's separation of components into "renderers" and "editors." This separation was (in my opinion) a poor design choice and only serves to complicate matters when trying to extend Swing components.

Swing 中的所有聚合组件——即由​​其他组件(如 JTable、JTree 或 JComboBox)组成的组件——都可以高度定制。例如,JTable 组件通常显示 JLabel 组件的网格,但它也可以显示 JButton、JTextField 甚至其他 JTable。然而,让这些聚合组件显示非默认对象是很容易的部分。由于 Swing 将组件分为“渲染器”和“编辑器”,让它们正确响应键盘和鼠标事件是一项艰巨的任务。这种分离(在我看来)是一个糟糕的设计选择,只会在尝试扩展 Swing 组件时使问题复杂化。

To see what I mean, try enhancing Swing's JList component so that it displays checkboxes instead of labels. According to Swing philosophy, this task requires implementing two interfaces: ListCellRenderer (for drawing the checkboxes) and CellEditor (for handling keyboard and mouse events on the checkboxes). Implementing the ListCellRenderer interface is easy enough, but the CellEditor interface can be rather clumsy and hard to understand. In this particular case, I would suggest forgetting CellEditor entirely and to handle input events directly, as shown in the following code.

要了解我的意思,请尝试增强 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;
      }
   }
}

Here, I intercept mouse clicks from the listbox and simulate a click on the appropriate checkbox. The result is a "CheckBoxList" component that is both simpler and smaller than an equivalent component using the CellEditor interface. To use the class, simply instantiate it, then pass it an array of JCheckBox objects (or subclasses of JCheckBox objects) by calling setListData. Note that the checkboxes in this component will not respond to keypresses (i.e. the spacebar), but you could always add your own key listener if needed.

在这里,我拦截了来自列表框的鼠标点击并模拟了对相应复选框的点击。结果是一个“CheckBoxList”组件,它比使用 CellEditor 接口的等效组件更简单和更小。要使用该类,只需将其实例化,然后通过调用 setListData 将 JCheckBox 对象(或 JCheckBox 对象的子类)数组传递给它。请注意,此组件中的复选框不会响应按键(即空格键),但如果需要,您始终可以添加自己的按键侦听器。

Source: DevX.com

资料来源:DevX.com