Вопрос

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

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

Это было полезно?

Решение

Создайте индивидуальный ListCellRenderer и назначьте его JList.

Этот обычай ListCellRenderer должен вернуть JCheckbox в реализации getListCellRendererComponent(...) метод.

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

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

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

ListCellRenderer

Другие советы

Замечательный ответ это 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таблица а не JList и поскольку рендеринг флажка по умолчанию довольно уродлив, я, вероятно, захочу добавить собственный ТаблицаМодель, CellRenderer и Редактор ячеек для представления логического значения.Конечно, я предполагаю, что это уже делалось миллиард раз.Солнце имеет хорошие примеры.

Просто реализуйте 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 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);

А ДефолтЛистМодель являются универсальными, и поэтому вы можете использовать методы, указанные API JAVA 7. здесь так:

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

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

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

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

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

Вот лишь небольшое дополнение к 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();
                }
            }
        }
        });

Все агрегатные компоненты в Swing, то есть компоненты, составляющие другие компоненты, такие как JTable, JTree или JComboBox, могут быть легко настроены.Например, компонент JTable обычно отображает сетку компонентов JLabel, но он также может отображать JButtons, JTextFields или даже другие JTables.Однако заставить эти агрегатные компоненты отображать объекты, отличные от стандартных, — это самая простая задача.Заставлять их правильно реагировать на события клавиатуры и мыши - гораздо более сложная задача, из -за разделения компонентов Swing на «рендереи» и «редакторы». Это разделение было (на мой взгляд) плохим выбором дизайна и служит для усложнения вопросов только при попытке расширить компоненты свинга.

Чтобы понять, что я имею в виду, попробуйте улучшить компонент JList Swing, чтобы он отображал флажки вместо меток.Согласно философии 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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top