Java 7: как реализовать drag & drop в Java?
в настоящее время я экспериментирую с drag&drop, используя обновление Java 7 21.
мои целевые операционные системы:
- Windows 7
- Ubuntu 12.04
- Mac OSX 10.6 / 10.8
требования:
перетащите файлы из файловой системы и поместите их в мое приложение Java (сделав копия файла во временный каталог) - > works for Linux & MacOSX & Окна
перетащите электронные письма из Thunderbird и поместите их в мое приложение Java (сохранение их как полных *.файл eml в файловой системе)
следующий код работает с простой файл падает в мое приложение для Windows, MacOSX и Ubuntu. Еще одним требованием является удаление электронной почты из Thunderbird в мое Java-приложение (Почта автоматически преобразуется в *.файл eml и хранится на диске). Это также отлично работает для Windows, но я получаю "Data Flavor не поддерживается исключение" в Ubuntu и MacOSX...
EDIT: я пробовал это с OpenJDK 7 на Ubuntu, но с этим даже обычные падения файлов не работают. Только с версией Oracle JDK.
есть ли у кого-нибудь идея, как исправить / достичь этого?
заранее большое спасибо!
вот простой пример executeable:
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);
}
}
4 ответов
на самом деле проблема не в коде Java... Это ошибка в самой ubuntu, в то время как Ubuntu Unity не поддерживает перетаскивание через два окна (в вашем приложении между Mozilla Thunderbird и Java-приложением). в то время как можно перетащить файл из файловой системы в окно..
чтобы подтвердить это, попробуйте перетащить почтовый файл из Thunderbird в окна браузера в качестве вложения Gmail,,, он не будет работать.
чтобы идти в ногу с этой ошибкой Обзор обновлений ошибок в Ubuntu ошибки Launchpad от: https://bugs.launchpad.net/unity / + ошибка/995039
вместо того, чтобы выбрасывать, почему бы не распечатать, какие данные вы получаете на переносимом, и посмотреть, есть ли один, который вы можете использовать. Что-то вроде
else {
for(DataFlavor f : transfer.getTransferDataFlavors()) {
System.out.println("flavor f:" + f + " type:" + f.getMimeType() + " javaClas:" + f.getDefaultRepresentationClass());
}
}
учитывая результат, есть хороший шанс, что вы можете увидеть, как сохранить его в файл.
Я думаю, следующая ссылка даст вам представление о проблеме :-
http://softwareisart.blogspot.in/2011/11/drag-and-drop-of-complex-custom-objects.html
вот работа вокруг того, как я, наконец, решил проблему на данный момент.
- если file-list-flavor не поддерживается, получите URL imap из drop-event
- откройте соединение imap с предоставленной информацией из URL imap
- откройте imap-store, imap-папку, поиск сообщения по 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();
}
}
}
}