Как мне сделать список с флажками в Java Swing? - PullRequest
29 голосов
/ 21 августа 2008

Как лучше всего иметь список элементов с флажком в Java Swing?

т.е. JList с элементами, которые имеют некоторый текст и флажок каждый?

Ответы [ 9 ]

21 голосов
/ 27 декабря 2009

Замечательный ответ: 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, с которым я связан.

16 голосов
/ 21 августа 2008

Создайте пользовательский ListCellRenderer и присвойте его JList.

Этот пользовательский ListCellRenderer должен возвращать JCheckbox в реализации метода getListCellRendererComponent(...).

Но это JCheckbox не будет редактируемым, если вы просто выбираете, когда этот JCheckbox должен быть отмечен галочкой или нет,

.

Например, показать его отмеченным, когда строка выбрана (параметр isSelected), но таким образом состояние проверки не будет поддерживаться, если выбор будет изменен. Лучше показать, что он проверен, сверившись с данными ниже ListModel, но затем вам нужно внедрить метод, который изменяет статус проверки данных, и уведомить об изменении JList для перерисовки.

Я опубликую пример кода позже, если вам это нужно

ListCellRenderer

11 голосов
/ 21 августа 2008

Я, вероятно, хотел бы использовать JTable , а не JList , и поскольку рендеринг по умолчанию флажка довольно уродлив, я, вероятно, хотел бы заглянуть в пользовательский TableModel , CellRenderer и CellEditor для представления логического значения. Конечно, я бы предположил, что это было сделано уже несколько раз. У Sun хороших примеров .

10 голосов
/ 30 ноября 2014

Просто внедрите 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

Подробности в Пользовательские компоненты рендеринга компонентов качания .

PS: Если вы хотите радиоэлементы, просто замените extends JCheckbox на extends JRadioButton.

5 голосов
/ 16 июля 2014

Лучшее решение для 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);

DefaultListModel являются общими, и поэтому вы можете использовать методы, указанные в JAVA 7 API здесь , например:

model.addElement(new JCheckBox("Checkbox1"));
model.addElement(new JCheckBox("Checkbox2"));
model.addElement(new JCheckBox("Checkbox3"));
3 голосов
/ 14 сентября 2013

Я рекомендую вам использовать JPanel с GridLayout 1 столбца. Добавьте флажки в JPanel и установите JPanel в качестве источника данных JScrollPane. А чтобы получить выбранные CheckBoxes, просто вызовите getComponents () JPanel, чтобы получить CheckBoxes.

3 голосов
/ 21 августа 2008

Вероятность того, что кто-то уже реализовал нужный вам виджет или утилиту, неплоха. Часть преимуществ большого сообщества OSS. Не нужно изобретать велосипед, если вы действительно не хотите делать это самостоятельно. В этом случае это было бы хорошим упражнением для обучения в CellRenderers and Editors.

Мой проект имел большой успех с JIDE. Требуемый компонент, список флажков, находится на общем уровне JIDE (который является OSS и размещен на java.net). Коммерческий материал тоже хорош, но он вам не нужен.

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

0 голосов
/ 22 сентября 2015

Все агрегатные компоненты в Swing, то есть компоненты, состоящие из других компонентов, таких как JTable, JTree или JComboBox, могут быть настроены индивидуально. Например, компонент JTable обычно отображает сетку компонентов JLabel, но он также может отображать JButtons, JTextFields или даже другие JTables. Однако получить эти агрегатные компоненты для отображения объектов не по умолчанию. Заставить их правильно реагировать на события клавиатуры и мыши - гораздо более сложная задача из-за разделения компонентов 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. Чтобы использовать класс, просто создайте его экземпляр, а затем передайте ему массив объектов JCheckBox (или подклассов объектов JCheckBox), вызвав setListData. Обратите внимание, что флажки в этом компоненте не будут реагировать на нажатия клавиш (то есть пробел), но вы всегда можете добавить свой собственный слушатель клавиш, если это необходимо.

Источник: DevX.com

0 голосов
/ 27 августа 2014

Вот лишь небольшое дополнение к JCheckBoxList от Rawa. Это добавит возможность выбора с помощью пробела. Если выбрано несколько элементов, для всех будет установлено инвертированное значение первого элемента.

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