概要

JTableのセルエディタとしてJComboBoxを設定し、そのセルを編集開始した場合、すぐにはドロップダウンリストを表示せず、選択状態になるように変更します。

サンプルコード

JComboBox<String> combo = new JComboBox<>(model);
combo.addAncestorListener(new AncestorListener() {
  @Override public void ancestorAdded(final AncestorEvent e) {
    System.out.println("ancestorAdded");
    e.getComponent().setEnabled(false);
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        System.out.println("invokeLater");
        e.getComponent().setEnabled(true);
      }
    });
  }

  @Override public void ancestorRemoved(AncestorEvent e) {
    System.out.println("ancestorRemoved");
  }

  @Override public void ancestorMoved(AncestorEvent e) {
    System.out.println("ancestorMoved");
  }
});
table.getColumnModel().getColumn(1).setCellEditor(new DefaultCellEditor(combo));
View in GitHub: Java, Kotlin

解説

  • Default
    • デフォルトのJComboBoxでセルエディタを作成し、そのセルでmousePressed(...)イベントが発生する
    • 別の列のフォーカスが存在する、または全セルにフォーカスが存在しない場合、ドロップダウンリストが表示される
    • 同じ列にフォーカスが存在する場合、選択状態になる(ドロップダウンリストは表示されない)
  • setEnabled
    • 動作を統一するために初回は常に選択状態になるように設定する
    • BasicComboPopup.Handler#mousePressed(...)がマウス左ボタンでJComboBox#isEnabled()==trueの場合は、BasicComboPopup#togglePopup()が実行される
    • そのため、セルエディタとして設定するJComboBoxAncestorListenerを追加
    • 編集開始でJTableにこのセルエディタが追加されてAncestorListener#ancestorAdded(...)が発生するが、JComboBox#setEnabled(false)としてBasicComboPopup#togglePopup()が実行されないようにブロック
    • EventQueue.invokeLater(...)を使用してマウス操作による一連のイベントの最後にJComboBox#setEnabled(true)を設定し、すでに編集開始状態にある同セルをもう一度押すとドロップダウンリストが表示されるように設定

参考リンク

コメント