2

我有一个带有一些项目的 jComboBox。目标是添加一个选项“全部”,这样当用户选择它时,所有可用的项目都会被选中。

是否可以使用 jComboBox 来完成,或者我最好使用另一个 jComponent (欢迎提出建议)。它要求它是一个下拉列表(因为它必须适合表格行)所以我猜它可能是一个带有复选框或类似内容的菜单。

NK

EDID:我试图在模型中放置一个假对象,该对象将被专门处理(以从模型中获取所有其他元素)但这真的不是一个好主意,因为这个假对象应该实现十几个接口而且它真的很难看.

4

3 回答 3

2

这是一个表格单元格编辑器,它会弹出一个包含复选框 JList 的对话框。它是来自这里和其他地方的各种示例的混搭。

编辑:添加了全选功能

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();
    }
  }
}
于 2013-09-10T16:12:20.313 回答
2

可以使用 JComboBox,但是,您需要为 JComboBox 实现 Renderer 和 ActionListener 并跟踪所选项目。例子:

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

(乍一看似乎有效,但可能充满了错误;-))

然后你可以像这样使用这个多选的东西:

// 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);
于 2013-09-10T15:51:39.577 回答
1

您可以尝试使用or模式JList代替(请参阅如何使用列表)来实现您的目标。SINGLE_SELECTION_INTERVALMULTIPLE_SELECTION_INTERVAL

 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);
      }
  });
于 2013-09-10T15:15:20.657 回答