「Explore (Windows)やFinder (Mac)からドラッグアンドドロップでファイルを受け取る」という操作ができると便利ですよね。
これはTransferHandlerというクラスを使って実装できます。
ドラッグアンドドロップでファイルを受け取る
早速コードを見てみましょう。
前半は起動のためのコードや、GUIを作るためのコードなので飛ばし読みしてください。
大切なのは59行目からです。
package jp.beourselves.open.sample.dropfiles;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.File;
import java.io.IOException;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.TransferHandler;
public class DropAndListFileName {
private JFrame frame;
private JTextArea textArea;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
DropAndListFileName window = new DropAndListFileName();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public DropAndListFileName() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JScrollPane scrollPane = new JScrollPane();
frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
textArea = new JTextArea();
scrollPane.setViewportView(textArea);
// ドロップ操作を有効にする
textArea.setTransferHandler(new DropFileHandler());
}
/**
* ドロップ操作の処理を行うクラス
*/
private class DropFileHandler extends TransferHandler {
/**
* ドロップされたものを受け取るか判断 (ファイルのときだけ受け取る)
*/
@Override
public boolean canImport(TransferSupport support) {
if (!support.isDrop()) {
// ドロップ操作でない場合は受け取らない
return false;
}
if (!support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
// ドロップされたのがファイルでない場合は受け取らない
return false;
}
return true;
}
/**
* ドロップされたファイルを受け取る
*/
@Override
public boolean importData(TransferSupport support) {
// 受け取っていいものか確認する
if (!canImport(support)) {
return false;
}
// ドロップ処理
Transferable t = support.getTransferable();
try {
// ファイルを受け取る
List files = (List) t.getTransferData(DataFlavor.javaFileListFlavor);
// テキストエリアに表示するファイル名リストを作成する
StringBuffer fileList = new StringBuffer();
for (File file : files){
fileList.append(file.getName());
fileList.append("\n");
}
// テキストエリアにファイル名のリストを表示する
textArea.setText(fileList.toString());
} catch (UnsupportedFlavorException | IOException e) {
e.printStackTrace();
}
return true;
}
}
}
実行すると、こんな画面が出てきます。

のっぺらぼうです。
JTextAreaが貼られただけ。

そのJTextAreaにファイルをドラッグすることで、ファイル名のリストが表示されます。


ドロップ操作の処理を行うクラスを作る
ドロップ操作の処理を行うクラス (DropFileHandler)を63行目から作っています。
このクラスはTransferHandlerクラスを継承し、次の2つのメソッドをオーバライドしています。
- canImport(TransferSupport support)
- importData(TransferSupport support)
canImport(TransferSupport support)メソッド
まずはcanImport(TransferSupport support)メソッド。
同名のメソッドが2つありますが、TransferHandler.TransferSupportクラスを引数とするメソッドを使うことが奨励されています。
このメソッドでは、ファイルなどがドラッグアンドドロップされてきたときに、受け取っていいものかを判定します。
68〜84行目を見てください。
/**
* ドロップされたものを受け取るか判断 (ファイルのときだけ受け取る)
*/
@Override
public boolean canImport(TransferSupport support) {
if (!support.isDrop()) {
// ドロップ操作でない場合は受け取らない
return false;
}
if (!support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
// ドロップされたのがファイルでない場合は受け取らない
return false;
}
return true;
}
ここでは2つの判定をしています。
- ドロップ操作か
- ドロップされたのは「ファイル」か
ドロップ操作か
TransferHandler.TransferSupportクラスのisDrop()メソッドを使うことで、ドロップ操作が行われたかを確認できます。
ドロップされたのは「ファイル」か
ドロップされているのがファイルかどうかは、TransferHandler.TransferSupportクラスのisDataFlavorSupported()メソッドで確認できます。
DataFlavor.javaFileListFlavorで「ファイル」かどうかの判定をします。
どちらも問題なければ、canImportはtrueを返すようになっています。
importData(TransferSupport support)メソッド
続いてimportData()メソッドです。
こちらも同名のメソッドが2つありますが、TransferHandler.TransferSupportクラスを引数とするメソッドを使うことが奨励されています。
このメソッドで実際にデータを受け取っています。
86〜115行目を見てください。
/**
* ドロップされたファイルを受け取る
*/
@Override
public boolean importData(TransferSupport support) {
// 受け取っていいものか確認する
if (!canImport(support)) {
return false;
}
// ドロップ処理
Transferable t = support.getTransferable();
try {
// ファイルを受け取る
List files = (List) t.getTransferData(DataFlavor.javaFileListFlavor);
// テキストエリアに表示するファイル名リストを作成する
StringBuffer fileList = new StringBuffer();
for (File file : files){
fileList.append(file.getName());
fileList.append("\n");
}
// テキストエリアにファイル名のリストを表示する
textArea.setText(fileList.toString());
} catch (UnsupportedFlavorException | IOException e) {
e.printStackTrace();
}
return true;
}
まずは先に紹介したcamImport()を使って、受け取っていいものか確認しています (91〜94行目)。
受け取っていいものであれば、受け取ります (96〜113行目)。
この際、ファイルは List<File> として受け取るというところがミソです (100行目)。
102〜110行目では、受け取ったファイルのファイル名を取得し、テキストエリアに貼り付けています。
setTransferHandler()でセットする
以上の処理を実装したDropFileHandlerクラスを、60行目でJTextAreaにセットしています。
// ドロップ操作を有効にする textArea.setTransferHandler(new DropFileHandler());
これで、JTextAreaにファイルをドロップしたら、DropFileHandlerの処理が発動して、ファイルを受け取ってくれるようになります。
おわりに
ファイルをドラッグアンドドロップで受け取るというのは、アプリとしては今や普通の操作になっていますよね。
最初この処理を書こうと思った時、面倒くさそうだと思ったのですが、やってみたらそれほど難しくなかったです。
ファイルを List<File> で受け取るあたりでちょっとハマったくらいですかね (^^;
いつでも使えそうなので、マスターしておくと重宝しそうです。
元大手電機メーカのシステムエンジニア。
詳しくはこのサイトについての「サイト管理者について」をご覧ください。

