Java 7: How to implement drag & drop in Java?

salocinx picture salocinx · May 1, 2013 · Viewed 7.5k times · Source

I am currently experimenting with drag&drop using Java 7 Update 21.

My target operating systems are:

  • Windows 7
  • Ubuntu 12.04
  • Mac OSX 10.6 / 10.8

The requirements are:

  • drag files from the filesystem and drop it to my Java application (making a copy of the file to a temporary directory) -> works for Linux & MacOSX & Windows

  • drag e-mails from Thunderbird and drop them to my Java application (saving them as complete *.eml file on the filesystem)

The following code works with simple file drops to my application for Windows, MacOSX and Ubuntu. A further requirement is to drop e-mails from Thunderbird to my Java application (the mail is automatically converted to an *.eml file and stored to disk). This also works fine for Windows but I get a "Data Flavor not supported exception" in Ubuntu and MacOSX...

EDIT: I tried it with OpenJDK 7 on Ubuntu, but with that, even normal file drops doesn't work. Only with the JDK version of Oracle.

Does somebody has an idea how to fix / achieve that?

Many thanks in advance!

Here's a simple executeable sample:

import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDropEvent;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.List;


public class DragDropTest extends javax.swing.JFrame {


    public DragDropTest() {
        initComponents();
        initDragAndDrop();
    }

    private void initDragAndDrop() {
        this.setDropTarget(new DropTarget(){
            @Override
            public synchronized void drop(DropTargetDropEvent dtde) {
                try {
                    Transferable transfer = dtde.getTransferable();
                    if(transfer.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
                        dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
                        List objects = (List)transfer.getTransferData(DataFlavor.javaFileListFlavor);
                        for(Object object : objects) {
                            if(object instanceof File) {
                                File source = (File)object;
                                File dest = new File(System.getProperty("user.home")+File.separator+source.getName());
                                Files.copy(Paths.get(source.getAbsolutePath()), Paths.get(dest.getAbsolutePath()), StandardCopyOption.REPLACE_EXISTING);
                                System.out.println("File copied from "+source.getAbsolutePath()+" to "+dest.getAbsolutePath());
                            }
                        }
                    } else if(transfer.isDataFlavorSupported(DataFlavor.stringFlavor)) {
                        dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
                        String type = (String)transfer.getTransferData(DataFlavor.stringFlavor);
                        System.err.println("Data flavor not supported: "+type);
                    } else {
                        System.err.println("Data flavor not supported.");
                    }
                } catch(UnsupportedFlavorException ex) {
                    System.err.println(ex.getMessage());
                } catch(IOException ex) {
                    System.err.println(ex.getMessage());
                } catch(Exception ex) {
                    System.err.println(ex.getMessage());
                } finally {
                    dtde.dropComplete(true);
                }
            }
        });
    }

    @SuppressWarnings("unchecked")                      
    private void initComponents() {

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Drag & Drop");
        setResizable(false);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 200, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 200, Short.MAX_VALUE)
        );

        pack();
    }                       

    public static void main(String args[]) {
        new DragDropTest().setVisible(true);
    }

}

Answer

Mohammed Alaghbari picture Mohammed Alaghbari · May 10, 2013

Actually the problem is not in your Java code... It's a bug in ubuntu itself while Ubuntu Unity doesn't support Drag and Drop across two Windows (In your application between Mozilla Thunderbird and Java App). while it's possible to a drag and drop a file from the file system to a window..

To confirm this try to drag a mail file from Thunderbird to a browser windows as Gmail Attachment,,, it will not work.

To keep up with this bug review Bug updates in Ubuntu Bugs Launchpad from: https://bugs.launchpad.net/unity/+bug/995039