概要

JComboBoxの上下矢印キーによる選択上下移動アクションがLookAndFeelごとに異なるのでこれを統一します。

サンプルコード

JComboBox<LookAndFeelInfo> combo = new LookAndFeelComboBox(model) {
  @Override public void updateUI() {
    super.updateUI();
    String name = getUI().getClass().getName();
    if (name.contains("MetalComboBoxUI") || name.contains("MotifComboBoxUI")) {
      InputMap im = getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
      im.put(KeyStroke.getKeyStroke("DOWN"), "selectNext2");
      im.put(KeyStroke.getKeyStroke("UP"), "selectPrevious2");
    }
  }
};
View in GitHub: Java, Kotlin

解説

  • MetalLookAndFeelMotifLookAndFeel
    • デフォルトは(DOWN)キーにselectNextアクション、(UP)キーにselectPreviousアクションが割り当てられている
    • selectNextアクションはドロップダウンリストが表示されている場合は下のアイテムに選択を移動、非表示の場合はドロップダウンリストを開く(選択状態は変化しない)
    • JComboBoxのドロップダウンリストを上矢印キーでも開くよう設定する
// @see javax/swing/plaf/basic/BasicComboBoxUI.java
else if (key == DOWN) {
  if (comboBox.isShowing() ) {
    if (comboBox.isPopupVisible()) {
      if (ui != null) {
        ui.selectNextPossibleValue();
      }
    } else {
      comboBox.setPopupVisible(true);
    }
  }
}
  • BasicLookAndFeelWindowsLookAndFeelNimbusLookAndFeel
    • デフォルトは(DOWN)キーにselectNext2アクション、(UP)キーにselectPrevious2アクションが割り当てられている
    • selectNext2selectPrevious2アクションではドロップダウンリストは開かずに選択アイテム移動が可能
      • 編集可能なJComboBoxJTableのセルエディタとなるJComboBoxの場合はselectNext2selectPrevious2アクションでもドロップダウンリストが開く
    • 上記のサンプル右側のJComboBoxではMetalLookAndFeelMotifLookAndFeelの場合もInputMap#put(KeyStroke.getKeyStroke("DOWN"), "selectNext2")などで上下矢印キーでselectNext2selectPrevious2アクションを使用するよう変更
      • このため選択されたLookAndFeelへのUIManager.setLookAndFeel(lookAndFeelName)での切り替えがドロップダウンリストを開かずに上下矢印キーのみで可能になる
// @see javax/swing/plaf/basic/BasicComboBoxUI.java
else if (key == DOWN_2) {
  // Special case in which pressing the arrow keys will not
  // make the popup appear - except for editable combo boxes
  // and combo boxes inside a table.
  if (comboBox.isShowing()) {
    if ((comboBox.isEditable() || (ui != null && ui.isTableCellEditor()))
        && !comboBox.isPopupVisible()) {
      comboBox.setPopupVisible(true);
    } else {
      if (ui != null) {
        ui.selectNextPossibleValue();
      }
    }
  }
}

参考リンク

コメント