概要

JComboBoxに選択できないJSeparatorを挿入します。

スクリーンショット

ComboBoxSeparator.png

サンプルコード

JComboBox<Object> combo = new JComboBox<>();
combo.setRenderer(new DefaultListCellRenderer() {
  @Override public Component getListCellRendererComponent(
      JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
    if (value instanceof JSeparator) {
      return (Component) value;
    } else {
      return super.getListCellRendererComponent(
          list, value, index, isSelected, cellHasFocus);
    }
  }
});
DefaultComboBoxModel model = new DefaultComboBoxModel() {
  @Override public void setSelectedItem(Object o) {
    if (o instanceof JSeparator) {
      return;
    }
    super.setSelectedItem(o);
  }
};
model.addElement("aaaaa");
model.addElement(new JSeparator());
model.addElement("bbbbb");
combo.setModel(model);
View in GitHub: Java, Kotlin

解説

  • ListCellRenderer
    • JSeparatorが選択された場合は、セル描画ComponentとしてJSeparatorを返すListCellRendererを設定
  • DefaultComboBoxModel
    • JSeparatorが選択された場合は何もしないよう、setSelectedItemメソッドをオーバーライド

  • DefaultComboBoxModel#setSelectedItemメソッドをオーバーライドする代わりに、以下のようにJSeparatorが選択された場合はひとつ前のItemに戻すようなItemListenerを追加しても同様
    combobox.addItemListener(new ItemListener() {
      private Object prev;
      @Override public void itemStateChanged(ItemEvent e) {
        if (e.getStateChange() == ItemEvent.SELECTED) {
          Object obj = e.getItem();
          if (obj instanceof JSeparator) {
            if (prev == null) {
              prev = combobox.getItemAt(0);
            }
            combobox.setSelectedItem(prev);
          } else {
            prev = obj;
          }
        }
      }
    });
    
  • UpDownキーでの選択状態移動を可能にする(JSeparatorなら飛ばす)場合は、以下のようなキーストロークのアクションを設定する必要がある
    Action up = new AbstractAction() {
      @Override public void actionPerformed(ActionEvent e) {
        int index = combobox.getSelectedIndex();
        if (index == 0) {
          return;
        }
        Object o = combobox.getItemAt(index - 1);
        if (o instanceof JSeparator) {
          combobox.setSelectedIndex(index - 2);
        } else {
          combobox.setSelectedIndex(index - 1);
        }
      }
    };
    Action down = new AbstractAction() {
      @Override public void actionPerformed(ActionEvent e) {
        int index = combobox.getSelectedIndex();
        if (index == combobox.getItemCount() - 1) {
          return;
        }
        Object o = combobox.getItemAt(index + 1);
        if (o instanceof JSeparator) {
          combobox.setSelectedIndex(index + 2);
        } else {
          combobox.setSelectedIndex(index + 1);
        }
      }
    };
    ActionMap am = combobox.getActionMap();
    am.put("selectPrevious3", up);
    am.put("selectNext3", down);
    InputMap im = combobox.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "selectPrevious3");
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_KP_UP, 0), "selectPrevious3");
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "selectNext3");
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_KP_DOWN, 0), "selectNext3");
    

参考リンク

コメント