web-dev-qa-db-ja.com

Swingでドラッグアンドドロップを使用してファイルパスを取得するにはどうすればよいですか?

Swingアプリケーションには、使用するために選択されたファイルのファイルパスを保持するJTextFieldがあります。現在、この値を設定するために使用されるJFileChooserがあります。ただし、ユーザーがこのJTextFieldにファイルをドラッグアンドドロップし、常にJFileChooserを使用する代わりに、そのファイルのファイルパスをJTextFieldに配置する機能を追加したいと思います。

これをどのように行うことができますか?

38
Ascalonian

最初に Swing DragDrop support を調べる必要があります。その後、異なるオペレーティングシステム用の小さなトリックがいくつかあります。処理が完了したら、drop()コールバックを処理します。このコールバックでは、TransferableのDataFlavorを確認する必要があります。

Windowsの場合は、 DataFlavor.isFlavorJavaFileListType() を確認するだけで、次のようなデータを取得できます。

List<File> dropppedFiles = (List<File>)transferable.getTransferData(DataFlavor.javaFileListFlavor)

Linux(およびおそらくSolaris)の場合、DataFlavorは少し複雑です。独自のDataFlavorを作成する必要があり、Transferableタイプは異なります

nixFileDataFlavor = new DataFlavor("text/uri-list;class=Java.lang.String");
String data = (String)transferable.getTransferData(nixFileDataFlavor);
for(StringTokenizer st = new StringTokenizer(data, "\r\n"); st.hasMoreTokens();)
{
    String token = st.nextToken().trim();
    if(token.startsWith("#") || token.isEmpty())
    {
         // comment line, by RFC 2483
         continue;
    }
    try
    {
         File file = new File(new URI(token))
         // store this somewhere
    }
    catch(...)
    {
       // do something good
       ....
    }
}
42
basszero

ファイルとフォルダーのドラッグアンドドロップを容易にするために使用できるクラスを含むプログラム例があります。

http://www.iharder.net/current/Java/filedrop/

これをWindows 7とUbuntu 10.10の両方でテストしましたが、どちらの環境でもうまく機能するようです。

それを使用するには、次のようなコードをコードに追加します。

  JPanel  myPanel = new JPanel();
  new  FileDrop( myPanel, new FileDrop.Listener()
  {   public void  filesDropped( Java.io.File[] files )
      {   
          // handle file drop
          ...
      }   // end filesDropped
  }); // end FileDrop.Listener
33
Mr Ed

この比較的複雑なテーマの調査にあまり時間をかけたくなく、Windowsを使用している場合(またはJava 7以降)を使用している場合、ここで簡単な例を紹介します。 JTextAreaをドロップターゲットとしてドロップしたファイル:

JTextArea myPanel = new JTextArea();
myPanel.setDropTarget(new DropTarget() {
    public synchronized void drop(DropTargetDropEvent evt) {
        try {
            evt.acceptDrop(DnDConstants.ACTION_COPY);
            List<File> droppedFiles = (List<File>)
                evt.getTransferable().getTransferData(DataFlavor.javaFileListFlavor);
            for (File file : droppedFiles) {
                // process files
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
});
28
rustyx

これは古い質問ですが、現在の答えは少し時代遅れです。

  • jDK 1.6以降、クラス「TransferHandler」は新しい(上書きされた)メソッドで使用する必要があります
  • linuxのサポートが大幅に改善され、カスタム処理が不要になりました

これはLinux(KDE5)およびWindows 7で機能します。

final class FileDropHandler extends TransferHandler {
    @Override
    public boolean canImport(TransferHandler.TransferSupport support) {
        for (DataFlavor flavor : support.getDataFlavors()) {
            if (flavor.isFlavorJavaFileListType()) {
                return true;
            }
        }
        return false;
    }

    @Override
    @SuppressWarnings("unchecked")
    public boolean importData(TransferHandler.TransferSupport support) {
        if (!this.canImport(support))
            return false;

        List<File> files;
        try {
            files = (List<File>) support.getTransferable()
                    .getTransferData(DataFlavor.javaFileListFlavor);
        } catch (UnsupportedFlavorException | IOException ex) {
            // should never happen (or JDK is buggy)
            return false;
        }

        for (File file: files) {
            // do something...
        }
        return true;
    }
}

あらゆるコンポーネントで使用します

myComponent.setTransferHandler(new FileDropHandler());
15
ABika