How to select all items in java swing JComboBox or any other similar jComponent

5.3k views Asked by At

I have a jComboBox with a few items. The goal is to add an option "All" so when the user select it all the items available would be selected.

Is it possible to do it with a jComboBox or I better use another jComponent (recommendations are welcome). It's required that it's a dropdown list (because it must fit inside a table row) so I guess it could be a menu with checkboxes or something similar.

NK

EDID: I've tried to put a fake object in the model which would be handled specifically (to get all other elements from the model) but it's really not a good idea as this fake object should implement a dozen of interfaces and it's really ugly.

3

There are 3 answers

2
t_over On

It is possible with a JComboBox, however, you need to implement a Renderer and ActionListener for the JComboBox and keep track of the selected items. Example:

private class MultiSelectionHandler<ComboBoxItemType> extends BasicComboBoxRenderer implements ActionListener{

    private static final long serialVersionUID = 1L;
    private ArrayList<Object> selected = new ArrayList<Object>();
    private JComboBox<ComboBoxItemType> comboBox;

    public MultiSelectionHandler(JComboBox<ComboBoxItemType> comboBox){
        this.comboBox = comboBox;
        comboBox.addActionListener(this);
        comboBox.setRenderer(this);
        selected.add(comboBox.getSelectedItem());
    }

    @Override
    public void actionPerformed(ActionEvent e) {

        // Get the now selected item
        ComboBoxItemType selectedItem = comboBox.getItemAt(comboBox.getSelectedIndex());

        if(selectedItem.equals("All")){
            // The the "All"-item has been chosen

            // Select all items (except the "All"-item)
            int itemcount = comboBox.getItemCount();
            for(int i=0; i<itemcount; i++){
                Object item = comboBox.getItemAt(i);
                if (!selected.contains(item) && !item.equals("All") ){
                    selected.add(item);
                }
            }
        } else {
            // Another option has been chosen
            // Toggle the selection
            if(selected.contains(selectedItem)) {  
                selected.remove(selectedItem);  
            } else if(!selected.contains(selectedItem)) {  
                selected.add(selectedItem);  
            }  
        }
    }

    @Override
    public Component getListCellRendererComponent(JList list,  
            Object value,  
            int index,  
            boolean isSelected,  
            boolean cellHasFocus) {  

        // Set the background and foreground colors, use the selection colors if the item
        // is in the selected list
        if (selected.contains(value)) {  
            setBackground(list.getSelectionBackground());  
            setForeground(list.getSelectionForeground());  
        } else {  
            setBackground(list.getBackground());  
            setForeground(list.getForeground());  
        }  

        // Set the text of the item
        setText((value == null) ? "" : value.toString());  
        return this;
    }
}

(it seems to work at first glance, but probably is littered with bugs ;-) )

Then you can use this multi-selection-thingy like this:

// Create the items
String[] arr = {"One", "Two", "Three", "All"};

// Create the model and the box
DefaultComboBoxModel<String> model = new DefaultComboBoxModel<String>(arr);  
JComboBox<String> box = new JComboBox<String>(model);

// Use the MultiSelectionHandler for rendering
new MultiSelectionHandler<String>(box);
3
dic19 On

You could try with JList instead (see How to Use Lists) using SINGLE_SELECTION_INTERVAL or MULTIPLE_SELECTION_INTERVAL mode to achieve your target.

 JList list = new JList(new DefaultListModel());
 list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);

 JButton selectAll = new JButton("Select All");
 selectAll.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
          DefaultListModel dlm = (DefaultListModel)list.getModel();                
          list.setSelectionInterval(0, dlm.getSize() - 1);
      }
  });
0
splungebob On

Here's a table cell editor that pops up a dialog that contains a JList of checkboxes. It's a mashup of a variety of examples from here and elsewhere.

EDIT: added the Select All feature

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;

import javax.swing.*;
import javax.swing.table.*;

/*
 * A table cell editor that pops up a JList of checkboxes.
 */
@SuppressWarnings("unchecked")
public class CheckListEditor extends DefaultCellEditor implements Runnable
{
  private PopupDialog popup;
  private JButton editorComp;
  private String currentText = "";

  public static void main(String[] args)
  {
    SwingUtilities.invokeLater(new CheckListEditor());
  }

  public void run()
  {
    String[] columnNames = { "Item", "Selections" };
    Object[][] data = { { "Item 1", "A" },
                        { "Item 2", "B" },
                        { "Item 3", "C" } };

    JTable table = new JTable(data, columnNames);
    table.getColumnModel().getColumn(1).setPreferredWidth(300);
    table.setPreferredScrollableViewportSize(table.getPreferredSize());

    CheckListEditor popupEditor = new CheckListEditor();
    popupEditor.setList(Arrays.asList(new String[]{"A", "B", "C"}));
    table.getColumnModel().getColumn(1).setCellEditor(popupEditor);

    JScrollPane scrollPane = new JScrollPane(table);
    scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

    JFrame frame = new JFrame("Multi-Select Editor");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().setLayout(new FlowLayout());
    frame.getContentPane().add(scrollPane);
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }

  public CheckListEditor()
  {
    super(new JTextField());
    setClickCountToStart(2);

    // Use a JButton as the editor component
    editorComp = new JButton();
    editorComp.setFont(editorComp.getFont().deriveFont(Font.PLAIN));
    editorComp.setBackground(Color.WHITE);
    editorComp.setBorderPainted(false);
    editorComp.setContentAreaFilled(false);
    editorComp.setHorizontalAlignment(SwingConstants.LEFT);

    // Set up the dialog where we do the actual editing
    popup = new PopupDialog();
  }

  @Override
  public Object getCellEditorValue()
  {
    return currentText;
  }

  @Override
  public Component getTableCellEditorComponent(JTable table, Object value,
      boolean isSelected, int row, int column)
  {
    SwingUtilities.invokeLater(new Runnable()
    {
      public void run()
      {
        popup.setValue(currentText);
        Point p = editorComp.getLocationOnScreen();
        popup.setLocation(p.x, p.y + editorComp.getSize().height);
        popup.setVisible(true);
        fireEditingStopped();
      }
    });

    currentText = value.toString();
    editorComp.setText(currentText);
    return editorComp;
  }

  public <T> void setList(List<T> items)
  {
    popup.setList(items);
  }

  /*
   * Dialog that contains the "editor" panel
   */
  class PopupDialog extends JDialog
  {
    private final String delimiter = ",";
    private JList jlist;

    public PopupDialog()
    {
      super((Frame) null, "Select", true);

      setUndecorated(true);
      getRootPane().setWindowDecorationStyle(JRootPane.NONE);

      jlist = new JList();
      jlist.setCellRenderer(new CheckBoxListRenderer());
      jlist.setPrototypeCellValue(new CheckListItem("12345678901234567890"));
      jlist.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
      jlist.setVisibleRowCount(5);
      jlist.addMouseListener(new MouseAdapter()
      {
        @Override
        public void mouseClicked(MouseEvent event)
        {
          selectItem(event.getPoint());
        }
      });

      JScrollPane scrollPane = new JScrollPane(jlist);
      scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

      JButton selectAll = new JButton("Select All");
      selectAll.addActionListener(new ActionListener()
      {
        public void actionPerformed(ActionEvent event)
        {
          selectAllItems();
        }
      });

      JButton ok = new JButton("OK");
      ok.addActionListener(new ActionListener()
      {
        public void actionPerformed(ActionEvent event)
        {
          closeDialog(true);
        }
      });

      JButton cancel = new JButton("Cancel");
      cancel.addActionListener(new ActionListener()
      {
        public void actionPerformed(ActionEvent event)
        {
          closeDialog(false);
        }
      });

      JPanel buttons = new JPanel();
      buttons.add(selectAll);
      buttons.add(ok);
      buttons.add(cancel);

      JPanel panel = new JPanel(new BorderLayout());
      panel.setBorder(BorderFactory.createLineBorder(Color.BLUE, 1));
      panel.add(scrollPane, BorderLayout.CENTER);
      panel.add(buttons, BorderLayout.SOUTH);
      setContentPane(panel);
      pack();

      getRootPane().setDefaultButton(ok);
    }

    private void selectAllItems()
    {
      ListModel model = jlist.getModel();
      for (int index = 0; index < model.getSize(); index++)
      {
        CheckListItem item = (CheckListItem) model.getElementAt(index);
        item.setSelected(true);
      }
      jlist.repaint();
    }

    /*
     * Save the changed text before hiding the popup
     */
    public void closeDialog(boolean commit)
    {
      if (commit)
      {
        currentText = getSelectedItems();
      }

      jlist.requestFocusInWindow();
      setVisible(false);
    }

    private void selectItem(Point point)
    {
      int index = jlist.locationToIndex(point);

      if (index >= 0)
      {
        CheckListItem item = (CheckListItem) jlist.getModel().getElementAt(index);
        item.setSelected(!item.isSelected());
        jlist.repaint(jlist.getCellBounds(index, index));
      }
    }

    private <T> void setList(List<T> items)
    {
      Vector<CheckListItem> listData = new Vector<CheckListItem>();
      for (T item : items)
      {
        listData.add(new CheckListItem(item));
      }
      jlist.setListData(listData);
    }

    public String getSelectedItems()
    {
      String text = "";
      ListModel model = jlist.getModel();

      for (int i = 0; i < model.getSize(); i++)
      {
        CheckListItem item = (CheckListItem) model.getElementAt(i);
        if (item.isSelected())
        {
          text += item.toString();
          text += delimiter;
        }
      }

      if (text.endsWith(delimiter))
      {
        text = text.substring(0, text.lastIndexOf(delimiter));
      }

      return text;
    }

    public void setValue(String value)
    {
      ListModel model = jlist.getModel();

      for (int i = 0; i < model.getSize(); i++)
      {
        ((CheckListItem) model.getElementAt(i)).setSelected(false);
      }

      String text = value == null ? "" : value.toString();
      String[] tokens = text.split(delimiter);

      for (String token : tokens)
      {
        for (int i = 0; i < model.getSize(); i++)
        {
          if (model.getElementAt(i).toString().equals(token))
          {
            ((CheckListItem) model.getElementAt(i)).setSelected(true);
          }
        }
      }

      jlist.clearSelection();
      jlist.ensureIndexIsVisible(0);
    }
  }

  private class CheckBoxListRenderer extends JCheckBox implements ListCellRenderer
  {
    public Component getListCellRendererComponent(JList comp, Object value, int index,
                                                  boolean isSelected, boolean hasFocus)
    {
      setEnabled(comp.isEnabled());
      setSelected(((CheckListItem) value).isSelected());
      setFont(comp.getFont());
      setText(value.toString());

      if (isSelected)
      {
        setBackground(comp.getSelectionBackground());
        setForeground(comp.getSelectionForeground());
      }
      else
      {
        setBackground(comp.getBackground());
        setForeground(comp.getForeground());
      }

      return this;
    }
  }

  private class CheckListItem
  {
    private Object item;
    private boolean selected;

    public CheckListItem(Object item)
    {
      this.item = item;
    }

    public boolean isSelected()
    {
      return selected;
    }

    public void setSelected(boolean isSelected)
    {
      this.selected = isSelected;
    }

    @Override
    public String toString()
    {
      return item.toString();
    }
  }
}