简体   繁体   English

Java 7:如何在Java中实现拖放?

[英]Java 7: How to implement drag & drop in Java?

I am currently experimenting with drag&drop using Java 7 Update 21. 我目前正在尝试使用Java 7 Update 21进行拖放。

My target operating systems are: 我的目标操作系统是:

  • Windows 7 Windows 7的
  • Ubuntu 12.04 Ubuntu 12.04
  • Mac OSX 10.6 / 10.8 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 从文件系统拖动文件并将其拖放到我的Java应用程序(将文件的副本复制到临时目录) - >适用于Linux和MacOSX和Windows

  • drag e-mails from Thunderbird and drop them to my Java application (saving them as complete *.eml file on the filesystem) 从Thunderbird拖动电子邮件并将它们放到我的Java应用程序中(将它们保存为文件系统上的完整* .eml文件)

The following code works with simple file drops to my application for Windows, MacOSX and Ubuntu. 以下代码适用于Windows,MacOSX 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). 进一步的要求是从Thunderbird中删除电子邮件到我的Java应用程序(邮件自动转换为* .eml文件并存储到磁盘)。 This also works fine for Windows but I get a "Data Flavor not supported exception" in Ubuntu and MacOSX... 这对Windows也适用,但我在Ubuntu和MacOSX中得到了“Data Flavor not supported exception” ...

EDIT: I tried it with OpenJDK 7 on Ubuntu, but with that, even normal file drops doesn't work. 编辑:我在Ubuntu上尝试使用OpenJDK 7,但有了这个,即使是普通的文件丢弃也行不通。 Only with the JDK version of Oracle. 仅适用于Oracle的JDK版本。

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);
    }

}

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). 实际上问题不在你的Java代码中...这是ubuntu本身的一个错误,而Ubuntu Unity不支持跨两个Windows的拖放(在Mozilla Thunderbird和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. 要确认这一点,请尝试将邮件文件从Thunderbird拖到浏览器窗口作为Gmail附件,它将无法正常工作。

To keep up with this bug review Bug updates in Ubuntu Bugs Launchpad from: https://bugs.launchpad.net/unity/+bug/995039 为了跟上这个错误,请查看Ubuntu Bugs Launchpad中的Bug更新: https//bugs.launchpad.net/unity/+bug/995039

Instead of throwing, why not print out what data flavors you get on the transferable, and see if there is one you can use. 为什么不打印出可转让的数据风格,而不是抛出,看看是否有可以使用的数据风格。 Something like, 就像是,

 else { 
      for(DataFlavor f : transfer.getTransferDataFlavors()) {
             System.out.println("flavor f:" + f + " type:" + f.getMimeType() + " javaClas:" + f.getDefaultRepresentationClass());  
      }
 }

Given the output of that, there is a good chance you can see how to save it to a file. 鉴于其输出,您很有可能看到如何将其保存到文件中。

I guess the following link will give you idea about the problem :- 我想以下链接会让您了解问题: -

http://softwareisart.blogspot.in/2011/11/drag-and-drop-of-complex-custom-objects.html http://softwareisart.blogspot.in/2011/11/drag-and-drop-of-complex-custom-objects.html

Here's a work-around how I finally solved the problem for the moment. 这是我最终解决问题的方法。

  1. if file-list-flavor is not supported, get imap URL from drop-event 如果不支持file-list-flavor,请从drop-event获取imap URL
  2. open an imap connection with the provided information from the imap URL 使用来自imap URL的提供信息打开imap连接
  3. open imap-store, imap-folder, search message by UID and finally fetch message 打开imap-store,imap-folder,按UID搜索消息,最后获取消息
  4. convert to *.eml format 转换为* .eml格式

Required libraries: Apache Commons I/O and Java Mail API 必需的库: Apache Commons I / OJava Mail API

The following is the drop event implementation: 以下是drop事件实现:

scrDocuments.setDropTarget(new DropTarget() {
        @Override
        public synchronized void drop(DropTargetDropEvent evt) {
            try {
                Transferable transfer = evt.getTransferable();
                if(transfer.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
                    evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
                    List objects = (List)transfer.getTransferData(DataFlavor.javaFileListFlavor);
                    for(Object object : objects) {
                        if(object instanceof File) {
                            File file = (File)object;
                            // store file ...
                        }
                    }
                } else {
                    try {
                        String url = fetchURL(evt, transfer);
                        ImapMessage eml = new ImapMessage(url);
                        File file = eml.fetchMessage();
                        // store file ...
                    } catch(Exception ex) {
                        System.err.println(ex.getMessage());
                    }
                }
            } catch(Exception ex) {
                System.err.println(ex.getMessage());
            } finally {
                evt.dropComplete(true);
            }
        }
    });

private String fetchURL(DropTargetDropEvent evt, Transferable transfer) throws IOException, UnsupportedEncodingException, UnsupportedFlavorException {
    for(DataFlavor flavor : transfer.getTransferDataFlavors()) {
        if(flavor.isRepresentationClassInputStream()) {
            if(flavor.getHumanPresentableName().equals("application/x-moz-file-promise-url")) {
                evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
                BufferedReader reader = new BufferedReader(new InputStreamReader((InputStream)transfer.getTransferData(flavor), "ISO-8859-1"));
                String fAddress = reader.readLine();
                reader.close();
                return fAddress;
            }
        }
    }
    throw new IOException("No transferable object or stream found.");
}

And the following class looks-up the imap server and fetches the mail: 以下类查找imap服务器并获取邮件:

public class ImapMessage {

    private String authority;
    private String protocol;
    private String host;
    private int port;
    private String username;
    private String password;
    private String foldername;
    private long msgid;
    private String filename;
    private Message message;

    public ImapMessage(String url) throws IOException, MessagingException {
        parseURL(decodeURL(url));
    }

    @Override
    public String toString() {
        return "protocol: "+protocol+"\n"+
               "host: "+host+"\n"+
               "port: "+port+"\n"+
               "username: "+username+"\n"+
               "password: "+password+"\n"+
               "folder: "+foldername+"\n"+
               "msgid: "+msgid+"\n"+
               "filename: "+filename;
    }

    private String decodeURL(String url) throws IOException {
        if(url!=null && !url.isEmpty()) {
            String newurl = "";
            for(int i=0; i<url.length(); i+=2) {
                newurl+=url.substring(i, i+1);
            }
            newurl = StringUtils.replace(newurl, "%3E", ">");
            newurl = StringUtils.replace(newurl, "%20", " ");
            return newurl;
        } else {
            throw new IOException("The given URL is empty or invalid.");
        }
    }


    private void parseURL(String url) throws IOException, MalformedURLException {
        if(url!=null && !url.isEmpty()) {
            //<editor-fold defaultstate="collapsed" desc="Parse Protocol">
            if(url.startsWith("imaps")) {
                url = StringUtils.replace(url, "imaps", "http", 1);
                protocol = "imaps";
            } else if(url.startsWith("imap")) {
                url = StringUtils.replace(url, "imap", "http", 1);
                protocol = "imap";
            } else {
                throw new IOException("Unsupported protocol: "+url.substring(0, url.indexOf("://")));
            }

            try {
                URL newurl = new URL(url);
                String path = newurl.getPath();
                String query = newurl.getQuery();
                authority = newurl.getAuthority();
                host = newurl.getHost();
                port = newurl.getPort();
                username = newurl.getUserInfo();
                password = "provide your password here";
                foldername = path.substring(path.indexOf(">/")+2, path.lastIndexOf(">"));
                msgid = Long.parseLong(path.substring(path.lastIndexOf(">")+1, path.length()));
                filename = query.substring(query.indexOf("=")+1, query.length());
            } catch (MalformedURLException ex) {
                throw ex;
            }
        } else {
            throw new IOException("The given URL is empty or invalid.");
        }
    }

        public File fetchMessage() throws IOException, FileNotFoundException, MessagingException {

            Store store = null;
            Folder folder = null;
            File filepath = new File("/destination/directory");
            try {
                Properties props = System.getProperties();
                props.setProperty("mail.store.protocol", protocol);
                Session session = Session.getDefaultInstance(props, null);
                // session.setDebug(true);
                store = session.getStore(protocol);
                store.connect(host, port, username, password);
                folder = store.getFolder(foldername);
                folder.open(Folder.READ_ONLY);
                UIDFolder ufolder = (UIDFolder)folder;
                message = ufolder.getMessageByUID(msgid);
                if(message!=null) {
                    File file = null;
                    if(filename.equals("null")) {
                        file = new File(filepath.getAbsolutePath()+File.separator+Long.toString(System.nanoTime())+".eml");
                    } else {
                        file = new File(filepath.getAbsolutePath()+File.separator+filename);
                    }
                    message.writeTo(new FileOutputStream(file));
                    return file;
                } else {
                    throw new MessagingException("The requested e-mail could not be found on the mail server.");
                }
            } catch(Exception ex) {
                throw ex;
            } finally {
                if(folder!=null) {
                    folder.close(true);
                }
                if(store!=null) {
                    store.close();
                }
            }
        }

    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM