如何在 Java Swing 中制作带有复选框的列表?

发布于 2024-07-04 09:21:19 字数 85 浏览 10 评论 0原文

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

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

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

脸赞 2024-07-11 09:21:19

只需实现 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 组件渲染器

PS:如果您想要单选元素,只需将 extends JCheckbox 替换为 extends JRadioButton 即可。

Just implement a 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

Details at Custom swing component renderers.

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

潜移默化 2024-07-11 09:21:19

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

此自定义 ListCellRenderer 必须在 getListCellRendererComponent(...) 方法的实现中返回一个 JCheckbox

但是这个JCheckbox将不可编辑,只是在屏幕上进行简单的绘制,由您选择何时必须“勾选”或不“勾选”这个JCheckbox

例如,显示当选择该行时(参数isSelected),它会打勾,但是这样,如果选择发生变化,检查状态将不会保持。 最好显示它检查了 ListModel 下面的数据,但接下来由您来实现更改数据检查状态的方法,并将更改通知 JList< /code> 重新绘制。

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

ListCellRenderer

Create a custom ListCellRenderer and asign it to the JList.

This custom ListCellRenderer must return a JCheckbox in the implementantion of getListCellRendererComponent(...) method.

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

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 JList to be repainted.

I Will post sample code later if you need it

ListCellRenderer

千纸鹤 2024-07-11 09:21:19

一个很好的答案是这个 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 存在问题,我将修改此答案。

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 addCheckbox method like this (surely could be shorter, haven't used Java in a while):

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 CheckBoxList I encountered some problems (behaviors that didn't work). I'll modify this answer if I find problems with the CheckBoxList I linked to.

红颜悴 2024-07-11 09:21:19

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

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

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

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.

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.

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

じее 2024-07-11 09:21:19

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

要明白我的意思,请尝试增强 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

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.

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.

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.

Source: DevX.com

小红帽 2024-07-11 09:21:19

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

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.

九局 2024-07-11 09:21:19

我不喜欢将复选框放入模型中的解决方案。 模型应该只包含数据而不是显示元素。

我发现这个 http://www.java2s.com/Tutorials/Java /Swing_How_to/JList/Create_JList_of_CheckBox.htm

我对其进行了一些优化。 ACTIVE 标志代表复选框,SELECTED 标志显示光标所在的条目。

我的版本需要一个渲染器

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;
    }

}

现在您只需将其添加到您的 JList 中:

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
            }
        }
    }
});

I don't like the solutions that put a Checkbox into the model. The model should only contain data not display elements.

I found this http://www.java2s.com/Tutorials/Java/Swing_How_to/JList/Create_JList_of_CheckBox.htm

which I optimized a bit. The ACTIVE flag represents the Checkbox, the SELECTED flag shows what entry the cursor sits on.

my version requires a renderer

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;
    }

}

and an entity that got the active field:

public class Entity {

    private boolean active = true;

    public boolean isActive() {
        return active;
    }

    public void setActive(boolean isActive) {
        this.active = isActive;
    }

}

Now you only have to add this to your JList:

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
            }
        }
    }
});
放低过去 2024-07-11 09:21:19

这是使用复选框制作列表的另一个示例

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;
        }
    }
}

this is yet another example of making list with checkboxes

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;
        }
    }
}
思念满溢 2024-07-11 09:21:19

我可能希望使用 JTable 而不是 JList 并且由于复选框的默认渲染相当难看,我可能希望添加一个自定义 TableModelCellRendererCellEditor 来表示布尔值。 当然,我想这已经被做过无数次了。 Sun 有很好的例子

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

权谋诡计 2024-07-11 09:21:19

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());
    setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    addMouseListener(new MouseAdapter() {
      @Override
      public void mousePressed(MouseEvent e) {
        int index = locationToIndex(e.getPoint());
        if (index != -1) {
          JCheckBox checkbox = getModel().getElementAt(index);
          checkbox.setSelected(!checkbox.isSelected());
          repaint();
        }
      }
    });
  }

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

DefaultListModel 是通用的,因此您可以使用 JAVA 7 API 此处指定的方法像这样:

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

Better solution for Java 7 and newer

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.

My solution of the generic 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());
    setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    addMouseListener(new MouseAdapter() {
      @Override
      public void mousePressed(MouseEvent e) {
        int index = locationToIndex(e.getPoint());
        if (index != -1) {
          JCheckBox checkbox = getModel().getElementAt(index);
          checkbox.setSelected(!checkbox.isSelected());
          repaint();
        }
      }
    });
  }

  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.

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

The DefaultListModel are generic and thus you can use methods specified by JAVA 7 API here like this:

model.addElement(new JCheckBox("Checkbox1"));
model.addElement(new JCheckBox("Checkbox2"));
model.addElement(new JCheckBox("Checkbox3"));
泡沫很甜 2024-07-11 09:21:19

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

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.

        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();
                }
            }
        }
        });
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文