TL: DR Я хочу создать JComboBox
, который имеет JCheckboxes
вместо JLabels
везде, но в основной метке - в этом месте я хочу сохранить строку, представляющую значения всех отмеченных ящиков. Мне удалось заставить его работать, но у меня есть некоторые проблемы с тем, чтобы меню открывалось при щелчке мышью. Я также хочу, чтобы клавиши со стрелками просто перемещались по полю без выбора элементов и клавиши пробела для выбора.Создание JComboBox с флажками
Независимо от того, что я делаю, после моей ActionListener
уловов мыши и выбирает пункт меню закрывается через какой-либо другой слушатель вложен в JComboBox
и методе setPopupVisible
- он работает с моим уродливым обходным путем, но там должен быть лучше для этого ..
Я считаю, что мне нужно прослушиватель мыши на listBox
в классе BasicComboBoxUI
, но как мне туда добраться?
В небольшое количество кода, как я мог бы сократить его:
ComboCheckBoxModel:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class ComboCheckBoxModel extends DefaultListModel implements ComboBoxModel, ItemSelectable {
private List<String> items = new ArrayList<>();
private List<String> checkedItems = new ArrayList<>();
private String selectedItem;
public ComboCheckBoxModel(List<String> items) {
if(!items.isEmpty()) {
selectedItem = items.get(0);
}
this.items = items;
}
public void check(Object item) {
String itemAsString = item.toString();
if(checkedItems.contains(itemAsString)) {
checkedItems.remove(itemAsString);
} else {
checkedItems.add(itemAsString);
}
fireContentsChanged(this, items.indexOf(item), items.indexOf(item));
}
public String getDataStringRepresentation() {
return checkedItems.stream().sorted().collect(Collectors.joining(", "));
}
@Override
public void setSelectedItem(Object anItem) {
selectedItem = anItem.toString();
}
@Override
public Object getSelectedItem() {
return selectedItem;
}
@Override
public int getSize() {
return items.size();
}
@Override
public Object getElementAt(int index) {
return items.get(index);
}
public boolean isChecked(String stringValue) {
return checkedItems.contains(stringValue);
}
@Override
public Object[] getSelectedObjects() {
return items.toArray();
}
@Override
public void addItemListener(ItemListener l) {
}
@Override
public void removeItemListener(ItemListener l) {
}
}
JComboBox:
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.util.stream.Stream;
import static java.util.stream.Collectors.toList;
public class JComboCheckBox extends JComboBox {
private final ComboCheckBoxModel model = new ComboCheckBoxModel(Stream.of("bum", "kabum", "dabum").collect(toList()));
private boolean shouldntClose;
public JComboCheckBox() {
super();
setRenderer(new CheckBoxCellRenderer());
setModel(model);
addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (e.getModifiers() == InputEvent.BUTTON1_MASK) {
System.out.println("LPM MASK");
model.check(model.getSelectedItem());
shouldntClose = true;
}
}
});
}
@Override
protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) {
if (ks.getKeyCode() == KeyEvent.VK_SPACE && isPopupVisible()) {
if (ks.getKeyCode() == KeyEvent.VK_SPACE && condition == WHEN_FOCUSED && ks.isOnKeyRelease()) {
System.out.println("ks = [" + ks + "], e = [" + e + "], condition = [" + condition + "], pressed = [" + pressed + "]");
model.check(model.getSelectedItem());
}
return true;
}
return super.processKeyBinding(ks, e, condition, pressed);
}
@Override
public void setPopupVisible(boolean v) {
if (shouldntClose) {
shouldntClose = false;
return;
} else {
super.setPopupVisible(v);
}
}
@Override
public Object getSelectedItem() {
return model.getSelectedItem();
}
}
Cell Renderer:
import javax.swing.*;
import java.awt.*;
public class CheckBoxCellRenderer extends JCheckBox implements ListCellRenderer {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
ComboCheckBoxModel model = (ComboCheckBoxModel) list.getModel();
if (index != -1) {
String stringValue = value == null ? "null" : value.toString();
setText(stringValue);
boolean checked = model.isChecked(stringValue);
setSelected(checked);
if (isSelected) {
setBackground(list.getSelectionBackground());
setForeground(list.getSelectionForeground());
} else {
setBackground(list.getBackground());
setForeground(list.getForeground());
}
return this;
} else {
String stringValue = model.getDataStringRepresentation();
return new JLabel(stringValue);
}
}
}
Launcher:
import javax.swing.*;
public class Launcher {
public JFrame create() {
JFrame f=new JFrame("Type the name of frame");
f.add(new JComboCheckBox());
f.setSize(400,400);
return f;
}
public static void main(String[] args) {
Launcher launcher = new Launcher();
launcher.create().setVisible(true);
}
}