2016-05-11 17 views
0

TL:DRの代わりにJCheckboxesJComboBoxを作成しますが、メインラベルにはこの場所にすべてのチェックボックスの値を表す文字列を保持します。私はそれを動作させることができましたが、マウスクリックでメニューを開いたままにしておくのにはいくつかの問題があります。私はまた、選択する項目とスペースキーを選択せず​​に矢印キーでボックスをナビゲートするだけでよい。チェックボックス付きのJComboBoxの作成

どんなに私は何をすべきか、私のActionListenerキャッチマウスの後にメニューがJComboBox及び方法setPopupVisibleにネストされ、いくつかの他のリスナーを介して閉じ項目をクリックしないと選択 - それは私の醜い回避策で動作しますが、もっと良い方法があるように持っています

私はlistBoxののマウスリスナーが必要ですが、どうやってそこに着くのですか?

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

セルレンダリング:

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

ランチャー:私はそれを狭める可能性があるので、コードの

として少量

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

答えて

0

クラスBasicComboBoxUI内ではlistBoxが、どのように私はそこに着くのですか?

はlistBoxは(JList?)BasicComboPopupから得ることが可能である:

Accessible a = getAccessibleContext().getAccessibleChild(0); 
if (a instanceof BasicComboPopup) { 
    BasicComboPopup pop = (BasicComboPopup) a; 
    int index = pop.getList().getSelectedIndex(); 
    //... 
} 

ComboCheckBoxTest.java

import java.awt.*; 
import java.awt.event.*; 
import java.util.*; 
import java.util.List; 
import java.util.stream.Collectors; 
import javax.accessibility.*; 
import javax.swing.*; 
import javax.swing.plaf.basic.*; 

public class ComboCheckBoxTest { 
    public JComponent makeUI() { 
    CheckableItem[] m = { 
     new CheckableItem("bum", false), 
     new CheckableItem("kabum", false), 
     new CheckableItem("dabum", false) 
    }; 
    JPanel p = new JPanel(); 
    p.add(new JComboCheckBox<CheckableItem>(m)); 
    return p; 
    } 
    public static void main(String[] args) { 
    EventQueue.invokeLater(() -> { 
     JFrame f = new JFrame("Type the name of frame"); 
     f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     f.getContentPane().add(new ComboCheckBoxTest().makeUI()); 
     f.setSize(320, 240); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    }); 
    } 
} 

class CheckableItem { 
    public final String text; 
    public boolean selected; 
    protected CheckableItem(String text, boolean selected) { 
    this.text = text; 
    this.selected = selected; 
    } 
    @Override public String toString() { 
    return text; 
    } 
} 

class CheckBoxCellRenderer<E extends CheckableItem> implements ListCellRenderer<E> { 
    private final JLabel label = new JLabel(" "); 
    private final JCheckBox check = new JCheckBox(" "); 
    @Override public Component getListCellRendererComponent(
     JList list, CheckableItem value, int index, 
     boolean isSelected, boolean cellHasFocus) { 
    ListModel model = list.getModel(); 
    if (index < 0) { 
     label.setText(getDataStringRepresentation(model)); 
     return label; 
    } else { 
     check.setText(Objects.toString(value, "null")); 
     check.setSelected(value.selected); 
     if (isSelected) { 
     check.setBackground(list.getSelectionBackground()); 
     check.setForeground(list.getSelectionForeground()); 
     } else { 
     check.setBackground(list.getBackground()); 
     check.setForeground(list.getForeground()); 
     } 
     return check; 
    } 
    } 
    private String getDataStringRepresentation(ListModel model) { 
    List<String> sl = new ArrayList<>(); 
    for (int i = 0; i < model.getSize(); i++) { 
     Object o = model.getElementAt(i); 
     if (o instanceof CheckableItem && ((CheckableItem) o).selected) { 
     sl.add(o.toString()); 
     } 
    } 
    return sl.stream().sorted().collect(Collectors.joining(", ")); 
    } 
} 

class JComboCheckBox<E extends CheckableItem> extends JComboBox<E> { 
    private boolean shouldntClose; 
    private transient ActionListener listener; 

    public JComboCheckBox() { 
    super(); 
    } 

    public JComboCheckBox(E[] m) { 
    super(m); 
    } 

    @Override public Dimension getPreferredSize() { 
    return new Dimension(200, 20); 
    } 

    @Override public void updateUI() { 
    setRenderer(null); 
    removeActionListener(listener); 
    super.updateUI(); 
    listener = e -> { 
     if (e.getModifiers() == InputEvent.BUTTON1_MASK) { 
     System.out.println("LPM MASK: " + getSelectedIndex()); 
     updateItem(getSelectedIndex()); 
     shouldntClose = true; 
     } 
    }; 
    setRenderer(new CheckBoxCellRenderer<CheckableItem>()); 
    addActionListener(listener); 
    getInputMap(JComponent.WHEN_FOCUSED).put(
     KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "space-key-select"); 
    getActionMap().put("space-key-select", new AbstractAction() { 
     @Override public void actionPerformed(ActionEvent e) { 
     System.out.println("JComboBox#getSelectedIndex()" + getSelectedIndex()); 
     Accessible a = getAccessibleContext().getAccessibleChild(0); 
     if (a instanceof BasicComboPopup) { 
      BasicComboPopup pop = (BasicComboPopup) a; 
      int i = pop.getList().getSelectedIndex(); 
      System.out.println("JList#getSelectedIndex() " + i); 
      updateItem(i); 
     } 
     } 
    }); 
    } 

    private void updateItem(int index) { 
    if (isPopupVisible()) { 
     E item = getItemAt(index); 
     item.selected ^= true; 
     removeItemAt(index); 
     insertItemAt(item, index); 
     setSelectedItem(item); 
    } 
    } 

    @Override 
    public void setPopupVisible(boolean v) { 
    if (shouldntClose) { 
     shouldntClose = false; 
     return; 
    } else { 
     super.setPopupVisible(v); 
    } 
    } 
} 
関連する問題