How can I use Drag-and-Drop in Swing to get file path?
First you should look into Swing DragDrop support. After that there are few little tricks for different operating systems. Once you've got things going you'll be handling the drop() callback. In this callback you'll want to check the DataFlavor of the Transferable.
For Windows you can just check the DataFlavor.isFlavorJavaFileListType() and then get your data like this
List<File> dropppedFiles = (List<File>)transferable.getTransferData(DataFlavor.javaFileListFlavor)
For Linux (and probably Solaris) the DataFlavor is a little trickier. You'll need to make your own DataFlavor and the Transferable type will be different
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
....
}
}
In case you don't want to spend too much time researching this relatively complex subject, and you're on Java 7 or later, here's a quick example of how to accept dropped files with a JTextArea
as a drop target:
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();
}
}
});
There is an example program which contains a class which can be used for facilitating drag and drop for files and folders:
http://www.iharder.net/current/java/filedrop/
I tested this with both Windows 7 and Ubuntu 10.10, and it appears to work well in both environments.
To use it, you add something like this to your code:
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
I know this is an old question but the current answers are all a bit outdated:
- since JDK 1.6 the class 'TransferHandler' should be used with new (overwritten) methods
- support for Linux became a lot better, no need for custom handling
This works on Linux (KDE5) and 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;
}
}
Use it on any component with
myComponent.setTransferHandler(new FileDropHandler());