JComboBox 实现多选
类ComboCheckBoxEntry,用于保存JComboBoxde item信息
public class ComboCheckBoxEntry { boolean checked; boolean state; String uniqueCode; String value; public ComboCheckBoxEntry() { this.checked = false; this.state = true; this.uniqueCode = "-1"; this.value = "Empty Entry"; } public ComboCheckBoxEntry(String uniqueCode, String value) { this.checked = false; this.state = true; this.uniqueCode = uniqueCode; this.value = value; } public ComboCheckBoxEntry(boolean checked, String uniqueCode, String value) { this.checked = checked; this.state = true; this.uniqueCode = uniqueCode; this.value = value; } public ComboCheckBoxEntry(boolean checked, boolean state, String uniqueCode, String value) { this.checked = checked; this.state = state; this.uniqueCode = uniqueCode; this.value = value; } public boolean getChecked() { return checked; } public void setChecked(boolean checked) { this.checked = checked; } public String getUniqueCode() { return uniqueCode; } public String getValue() { return value; } public boolean getState() { return state; } }自定义render ComboCheckBoxRenderer
public class ComboCheckBoxRenderer extends JCheckBox implements ListCellRenderer, Serializable { protected static Border noFocusBorder; public ComboCheckBoxRenderer() { super(); if (noFocusBorder == null) { noFocusBorder = new EmptyBorder(1, 1, 1, 1); } setOpaque(true); setBorder(noFocusBorder); } public Component getListCellRendererComponent( JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { setComponentOrientation(list.getComponentOrientation()); if (isSelected) { setBackground(list.getSelectionBackground()); setForeground(list.getSelectionForeground()); } else { setBackground(list.getBackground()); setForeground(list.getForeground()); } if (value instanceof ComboCheckBoxEntry) { ComboCheckBoxEntry item = (ComboCheckBoxEntry) value; setSelected(item.getChecked()); setToolTipText(item.getValue()); setText(item.getValue()); } else { setText((value == null) ? "" : value.toString()); } setEnabled(list.isEnabled()); setFont(list.getFont()); setBorder((cellHasFocus) ? UIManager.getBorder("List.focusCellHighlightBorder") : noFocusBorder); return this; } }重写UI和POPUP ComboCheckBoxUI
public class ComboCheckBoxUI extends MetalComboBoxUI { private boolean isMultiSel = false; public int maxWidth = 300; public ComboCheckBoxUI() { } public ComboCheckBoxUI(int maxWidth) { this.maxWidth = maxWidth; } public static ComponentUI createUI(JComponent c) { return new ComboCheckBoxUI(); } @Override protected ComboPopup createPopup() { ComboCheckPopUp popUp = new ComboCheckPopUp(comboBox, maxWidth); popUp.getAccessibleContext().setAccessibleParent(comboBox); return popUp; } public class ComboCheckPopUp extends BasicComboPopup { private int width = -1; private int maxWidth = 300; public ComboCheckPopUp(JComboBox cBox, int maxWidth) { super(cBox); this.maxWidth = maxWidth; } @Override protected JScrollPane createScroller() { return new JScrollPane( list, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); } @Override protected MouseListener createListMouseListener() { return new CheckBoxListMouseHandler(); } @Override protected KeyListener createKeyListener() { return new CheckBoxKeyHandler(); } @Override public void show() { Dimension popupSize = comboBox.getSize(); Insets insets = getInsets(); popupSize.setSize(popupSize.width - (insets.right + insets.left), getPopupHeightForRowCount(comboBox.getMaximumRowCount())); int maxWidthOfCell = calcPreferredWidth(); width = maxWidthOfCell; if (comboBox.getItemCount() > comboBox.getMaximumRowCount()) { width += scroller.getVerticalScrollBar().getPreferredSize().width; } if (width > this.maxWidth) { width = this.maxWidth; } if (width < this.comboBox.getWidth()) { width = this.comboBox.getWidth(); } if (maxWidthOfCell > width) { popupSize.height += scroller.getHorizontalScrollBar().getPreferredSize().height; } Rectangle popupBounds = computePopupBounds(0, comboBox.getBounds().height, width, popupSize.height); scroller.setMaximumSize(popupBounds.getSize()); scroller.setPreferredSize(popupBounds.getSize()); scroller.setMinimumSize(popupBounds.getSize()); list.invalidate(); syncListSelectionWithComboBoxSelection(); list.ensureIndexIsVisible(list.getSelectedIndex()); setLightWeightPopupEnabled(comboBox.isLightWeightPopupEnabled()); show(comboBox, popupBounds.x, popupBounds.y); } private int calcPreferredWidth() { int prefferedWidth = 0; ListCellRenderer renderer = list.getCellRenderer(); for (int index = 0, count = list.getModel().getSize(); index < count; index++) { Object element = list.getModel().getElementAt(index); Component comp = renderer.getListCellRendererComponent(list, element, index, false, false); Dimension dim = comp.getPreferredSize(); if (dim.width > prefferedWidth) { prefferedWidth = dim.width; } } return prefferedWidth; } void syncListSelectionWithComboBoxSelection() { int selectedIndex = comboBox.getSelectedIndex(); if (selectedIndex == -1) { list.clearSelection(); } else { list.setSelectedIndex(selectedIndex); } } public void setPopupWidth(int width) { this.width = width; } protected class CheckBoxKeyHandler extends KeyAdapter { @Override public void keyPressed(KeyEvent e) { isMultiSel = e.isControlDown(); } @Override public void keyReleased(KeyEvent e) { isMultiSel = e.isControlDown(); } } protected class CheckBoxListMouseHandler extends MouseAdapter { @Override public void mousePressed(MouseEvent anEvent) { int index = list.getSelectedIndex(); ComboCheckBoxEntry item = (ComboCheckBoxEntry) list.getModel().getElementAt(index); boolean checked = !item.getChecked(); int size = list.getModel().getSize(); if (isMultiSel) { item.setChecked(checked); } else { for (int i = 0; i < size; i++) { ComboCheckBoxEntry ccbe = (ComboCheckBoxEntry) list.getModel().getElementAt(i); ccbe.setChecked(false); } item.setChecked(true); } updateListBoxSelectionForEvent(anEvent, false); Rectangle rect = list.getCellBounds(0, size - 1); list.repaint(rect); } @Override public void mouseReleased(MouseEvent anEvent) { if (!isMultiSel) { ComboCheckBoxEntry item = (ComboCheckBoxEntry) list.getSelectedValue(); if (item.checked) { comboBox.setSelectedIndex(list.getSelectedIndex()); comboBox.setPopupVisible(false); } } } } } }重写 JComboBox 以及测试
public class JComboCheckBox extends JComboBox { private int maxWidth = 300; public JComboCheckBox() { super(); setRenderer(new ComboCheckBoxRenderer()); updateUI(); } public JComboCheckBox(String[] items) { super(); setRenderer(new ComboCheckBoxRenderer()); addItems(items); updateUI(); } public JComboCheckBox(Vector<String> items) { super(); setRenderer(new ComboCheckBoxRenderer()); addItems(items.toArray(new String[0])); updateUI(); } public JComboCheckBox(int maxWidth) { super(); this.maxWidth = maxWidth; setRenderer(new ComboCheckBoxRenderer()); updateUI(); } public JComboCheckBox(String[] items, int maxWidth) { super(); this.maxWidth = maxWidth; setRenderer(new ComboCheckBoxRenderer()); addItems(items); updateUI(); } public JComboCheckBox(Vector<String> items, int maxWidth) { super(); this.maxWidth = maxWidth; setRenderer(new ComboCheckBoxRenderer()); addItems(items.toArray(new String[0])); updateUI(); } public void addItems(String[] items) { for (int i = 0; i < items.length; i++) { String string = items[i]; this.addItem(new ComboCheckBoxEntry(String.valueOf(i + 1), string)); } } public void addItem(ComboCheckBoxEntry item) { super.addItem(item); } public void addItem(boolean checked, boolean state, String id, String value) { super.addItem(new ComboCheckBoxEntry(checked, state, id, value)); } public String[] getCheckedCodes() { Vector values = new Vector(); DefaultComboBoxModel model = (DefaultComboBoxModel) getModel(); for (int i = 0; i < model.getSize(); i++) { ComboCheckBoxEntry item = (ComboCheckBoxEntry) model.getElementAt(i); boolean checked = item.getChecked(); if (checked) { values.add(item.getUniqueCode()); } } String[] retVal = new String[values.size()]; values.copyInto(retVal); return retVal; } public String[] getCheckedValues() { Vector values = new Vector(); DefaultComboBoxModel model = (DefaultComboBoxModel) getModel(); for (int i = 0; i < model.getSize(); i++) { ComboCheckBoxEntry item = (ComboCheckBoxEntry) model.getElementAt(i); boolean checked = item.getChecked(); if (checked) { values.add(item.getValue()); } } String[] retVal = new String[values.size()]; values.copyInto(retVal); return retVal; } @Override public void updateUI() { setUI(new ComboCheckBoxUI(maxWidth)); } public static void main(String[] args) { JFrame frame = new JFrame(); frame.setSize(650, 580); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel jPanel = new JPanel(); String[] values = new String[]{"1111111111111111111", "22", "33333333333333333333", "4444444444444", "55555555555555555", "6", "77", "6", "77", "6", "77"}; final JComboCheckBox checkBox = new JComboCheckBox(values); checkBox.setPreferredSize(new Dimension(150, 30)); jPanel.add(checkBox); JButton btnCode = new JButton("Code"); btnCode.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { for (String string : checkBox.getCheckedCodes()) { System.out.print(string + " "); } System.out.println(""); } }); jPanel.add(btnCode); JButton btnValue = new JButton("Value"); btnValue.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { for (String string : checkBox.getCheckedValues()) { System.out.print(string + " "); } System.out.println(""); } }); jPanel.add(btnValue); frame.getContentPane().add(jPanel); frame.setVisible(true); } }