【问题标题】:Java 7: How to implement drag & drop in Java?Java 7:如何在 Java 中实现拖放?
【发布时间】:2013-04-25 15:06:25
【问题描述】:

我目前正在使用 Java 7 Update 21 进行拖放试验。

我的目标操作系统是:

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

要求是:

  • 将文件从文件系统中拖放到我的 Java 应用程序中(制作一个 将文件复制到临时目录)-> 适用于 Linux & MacOSX & Windows

  • 将电子邮件从 Thunderbird 拖放到我的 Java 应用程序(保存 它们作为文件系统上的完整 *.eml 文件)

以下代码适用于我的 Windows、MacOSX Ubuntu 应用程序的简单文件拖放。另一个要求是将电子邮件从 Thunderbird 放到我的 Java 应用程序中(邮件会自动转换为 *.eml 文件并存储到磁盘中)。这也适用于 Windows,但我在 Ubuntu 和 MacOSX 中得到 "Data Flavor not supported exception"...

编辑:我在 Ubuntu 上使用 OpenJDK 7 进行了尝试,但是这样,即使是正常的文件删除也不起作用。仅适用于 JDK 版本的 Oracle。

有人知道如何解决/实现这一点吗?

非常感谢!

这是一个简单的可执行示例:

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

}

【问题讨论】:

    标签: java drag-and-drop drag java-7 thunderbird


    【解决方案1】:

    实际上问题不在于您的 Java 代码...这是 ubuntu 本身的一个错误,而 Ubuntu Unity 不支持跨两个 Windows 拖放(在您的应用程序中 Mozilla Thunderbird 和 Java App 之间)。虽然可以将文件从文件系统拖放到窗口中..

    要确认这一点,请尝试将邮件文件从 Thunderbird 拖到浏览器窗口作为 Gmail 附件,,但它不起作用。

    为了跟上这个错误审查 Ubuntu Bugs Launchpad 中的错误更新来自: https://bugs.launchpad.net/unity/+bug/995039

    【讨论】:

    • 感谢您的建议。我尝试使用“sudo apt-get purge mousetweaks”删除 Mousetweaks。但它仍然不起作用...... :-(
    【解决方案2】:

    与其扔,不如打印出你在可转移设备上获得的数据类型,看看是否有你可以使用的。比如,

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

    鉴于该输出,您很有可能会看到如何将其保存到文件中。

    【讨论】:

    • 进一步打印你得到的味道并尝试操纵它,也许将所有内容保存到文件中,然后看看什么是 .eml 虽然我怀疑只会设置一个。如果你没有得到任何可用的东西可能是 *nix 的雷鸟的问题
    【解决方案3】:

    我想下面的链接会让你对这个问题有所了解:-

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

    【讨论】:

      【解决方案4】:

      这是我目前最终解决问题的方法。

      1. 如果不支持 file-list-flavor,则从 drop-event 获取 imap URL
      2. 使用 imap URL 中提供的信息打开 imap 连接
      3. 打开 imap-store、imap-folder,通过 UID 搜索消息,最后获取消息
      4. 转换为 *.eml 格式

      所需库:Apache Commons I/OJava Mail API

      下面是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.");
      }
      

      以下类查找 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();
                      }
                  }
              }
      
          }
      

      【讨论】:

        猜你喜欢
        • 2012-04-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多