概要

JFileChooserTransferHandlerを設定してFileDirectoryをドロップ可能にします。

サンプルコード

chooser.setTransferHandler(new FileChooserTransferHandler());
// ...
class FileChooserTransferHandler extends TransferHandler {
  @Override public boolean canImport(TransferSupport support) {
    boolean canDrop = support.isDataFlavorSupported(DataFlavor.javaFileListFlavor);
    boolean isTarget = support.getComponent() instanceof JFileChooser;
    return support.isDrop() && canDrop && isTarget; // && !isMultiSelection;
  }

  @Override public boolean importData(TransferSupport support) {
    try {
      JFileChooser fc = (JFileChooser) support.getComponent();
      List<?> list = (List<?>) support.getTransferable().getTransferData(DataFlavor.javaFileListFlavor);
      File[] files = new File[list.size()];
      for (int i = 0; i < list.size(); i++) {
        files[i] = (File) list.get(i);
      }
      if (fc.isMultiSelectionEnabled()) {
        fc.setSelectedFiles(files);
      } else {
        File f = files[0];
        if (f.isDirectory()) {
          fc.setCurrentDirectory(f);
        } else {
          fc.setSelectedFile(f);
        }
      }
      return true;
    } catch (IOException | UnsupportedFlavorException ex) {
      return false;
    }
  }
}
View in GitHub: Java, Kotlin

解説

  • Default
    • JFileChooserJTextFieldに文字列はドロップ可能だがファイルはドロップ不可
  • TransferHandler
    • JFileChooser内のJTableJListJTextField以外にファイルをドロップ可能にするTransferHandlerを設定
    • JFileChooser#setMultiSelectionEnabled(true)の場合、選択された複数ファイル(ディレクトリを除く)のファイル名がJTextFieldに表示される
    • JFileChooser#setMultiSelectionEnabled(false)の場合、選択された複数ファイルの先頭ファイルがドロップの対象になる
      • ドロップの対象ファイルがディレクトリの場合、JFileChooser#setCurrentDirectory(dir)でカレントディレクトリを変更
      • ドロップの対象ファイルがファイルの場合、JFileChooser#setSelectedFile(file)で選択ファイルを変更

  • 以下のようにTransferHandler#canImport(...)をオーバーライドして複数ファイルが選択されている場合はドロップを拒否すると、InvalidDnDOperationException: No drop currentが発生する?
class FileChooserTransferHandler extends TransferHandler {
  @Override public boolean canImport(TransferSupport support) {
    boolean canDrop = support.isDataFlavorSupported(DataFlavor.javaFileListFlavor);
    boolean isTarget = support.getComponent() instanceof JFileChooser;
    boolean isMultiSelection = true;
    if (isTarget && canDrop) {
      try {
        JFileChooser fc = (JFileChooser) support.getComponent();
        // XXX: java.awt.dnd.InvalidDnDOperationException: No drop current
        List<?> list = (List<?>) support.getTransferable().getTransferData(DataFlavor.javaFileListFlavor);
        isMultiSelection = list.size() != 1;
      } catch (IOException | UnsupportedFlavorException ex) {
        ex.printStackTrace();
      }
    }
    return support.isDrop() && canDrop && isTarget && !isMultiSelection;
  }

参考リンク

コメント