Java 7:如何在 Java 中实现拖放?
Posted
技术标签:
【中文标题】Java 7:如何在 Java 中实现拖放?【英文标题】:Java 7: How to implement drag & drop in 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);
【问题讨论】:
【参考方案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】:这是我目前最终解决问题的方法。
-
如果不支持 file-list-flavor,则从 drop-event 获取 imap URL
使用 imap URL 中提供的信息打开 imap 连接
打开 imap-store、imap-folder,通过 UID 搜索消息,最后获取消息
转换为 *.eml 格式
所需库:Apache Commons I/O 和 Java 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();
【讨论】:
以上是关于Java 7:如何在 Java 中实现拖放?的主要内容,如果未能解决你的问题,请参考以下文章