概要

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) {}
  @Override public void ancestorMoved(AncestorEvent e) {}
});
table.getColumnModel().getColumn(1).setCellEditor(new DefaultCellEditor(combo));
view all

解説

  • 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)を設定し、すでに編集開始状態にある同セルをもう一度押すとドロップダウンリストが表示されるように設定

参考リンク

コメント