• category: swing folder: FileChooserCancelEdit title: JFileChooserの詳細表示でファイル名が編集中の場合はそれをキャンセルする tags: [JFileChooser, JTable] author: aterai pubdate: 2018-10-22T17:08:54+09:00 description: JFileChooserを詳細表示モードで表示したとき、前回のファイル名編集が継続中の場合はそれをキャンセルします。 image: https://drive.google.com/uc?id=1mmE2-oPYGfml1EHlPd7pXonxZxiGUWpelQ

概要

JFileChooserを詳細表示モードで表示したとき、前回のファイル名編集が継続中の場合はそれをキャンセルします。

サンプルコード

JFileChooser fileChooser1 = new JFileChooser();
JButton button1 = new JButton("removeEditor");
button1.addActionListener(e -> {
  Optional.ofNullable(fileChooser.getActionMap().get("viewTypeDetails"))
    .ifPresent(a -> {
      a.actionPerformed(new ActionEvent(e.getSource(), e.getID(), "viewTypeDetails"));
    });
  stream(fileChooser1)
    .filter(JTable.class::isInstance).map(JTable.class::cast)
    .findFirst()
    .filter(JTable::isEditing).ifPresent(JTable::removeEditor);
  int retvalue = fileChooser1.showOpenDialog(getRootPane());
  if (retvalue == JFileChooser.APPROVE_OPTION) {
    append(log, fileChooser1.getSelectedFile().getAbsolutePath());
  }
});
View in GitHub: Java, Kotlin

解説

  • default
    • JFileChooserの詳細表示モード(JTable)でファイルをマウスのダブルクリックで選択してダイアログを閉じた場合、次回JFileChooserを再表示するとファイル名セルの編集状態が継続している場合がある
    • 再現が不安定?なので仕様ではなくバグなのかもしれない
    • Java 21で以下のようにBasicTableUI.javaが修正されて発生しなくなった?
      #spanend
          } else if (key == CANCEL_EDITING) {
              if (table.isEditing()) {
                  table.getCellEditor().cancelCellEditing();
              }
              table.removeEditor();
              // ...
      #spanadd
      
  • removeEditor
    • JFileChooserを表示する前に子JTableを検索してJTable#removeEditor()メソッドを実行し、セルエディタを除去
    • sun.swing.FilePane#cancelEdit()メソッドが内部でdetailsTable.getCellEditor().cancelCellEditing();を実行して編集状態を解除しているがプライベートなので使用しづらい

参考リンク

  • Containerの子Componentを再帰的にすべて取得する
  • JTableのセルの編集をコミット
    • JFileChooserの詳細表示モードで使用するJTabletable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);を設定すれば、フォーカスが無くなった時点で編集は破棄される
    • JFileChooserの詳細表示モードで使用するJTabletable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);を設定すればフォーカスが無くなった時点で編集は破棄される
  • JFileChooserを編集不可にする
    • JFileChooserでファイル名を編集する必要がない場合は、UIManager.put("FileChooser.readOnly", Boolean.TRUE);と編集不可にすればこの問題は発生しない
    • JFileChooserでファイル名を編集する必要がない場合はUIManager.put("FileChooser.readOnly", Boolean.TRUE);と編集不可にすればこの問題は発生しない

コメント