问题描述
有人知道 JDK1.6 和 JDK1.7 之间拖放行为的差异吗?在将 URL 从浏览器拖放到需要支持 JDK1.5、JDK1.6 和 JDK1.7 的应用程序上时,我遇到了一个差异(如下所示).我现在想知道是否存在其他差异,以及它们是否记录在某处.
Does anybody know about differences in the drag-and-drop behavior between JDK1.6 and JDK1.7 ? I encountered a difference (illustrated below) when drag-and-dropping an URL from a browser onto an application which needs to support JDK1.5, JDK1.6 and JDK1.7 . I am now wondering whether other differences exists and if they are documented somewhere.
我遇到的不同行为是通过单击并将 URL 从浏览器(不是从地址栏而是从页面)拖放到 Java 应用程序上来拖放 URL.在 JDK1.6 上,Transferable 不支持 DataFlavor.javaFileListFlavor
而在 JDK1.7 上它支持(尽管在请求其传输数据时会得到一个空列表).下面的代码说明了这个问题.它会打开一个 JFrame
,您可以在其中拖放一个 URL,例如 http://www.google.com 并打印出它是使用文件列表风格还是 URI 列表风格
The different behavior I encountered is when drag-and-drop an URL from a browser (not from the address bar but from the page) by click-and-drag the URL onto the Java application. On JDK1.6, the Transferable does not support the DataFlavor.javaFileListFlavor
and on JDK1.7 it does (although when requesting for its transfer data you get an empty list). The following code illustrates the issue. It opens a JFrame
on which you can drag-and-drop an URL like http://www.google.com and which prints out whether it uses the file list flavor or the URI-list flavor
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.TransferHandler;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
public class DragAndDropTester {
private static DataFlavor URI_LIST_FLAVOR = null;
static {
try {
URI_LIST_FLAVOR = new DataFlavor( "text/uri-list;class=java.lang.String" );
}
catch ( ClassNotFoundException ignore ) {
}
}
public static void main( String[] args ) {
try {
EventQueue.invokeAndWait( new Runnable() {
public void run() {
JFrame testFrame = new JFrame( "Test" );
JPanel contents = new JPanel( new BorderLayout() );
contents.add( new JLabel( "TestLabel" ), BorderLayout.CENTER );
contents.setTransferHandler( createTransferHandler() );
testFrame.getContentPane().add( contents );
testFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
testFrame.setSize( 200, 200 );
testFrame.setVisible( true );
}
} );
} catch ( InterruptedException e ) {
throw new RuntimeException( e );
} catch ( InvocationTargetException e ) {
throw new RuntimeException( e );
}
}
private static TransferHandler createTransferHandler(){
return new TransferHandler( ){
@Override
public boolean importData( JComponent comp, Transferable aTransferable ) {
try {
if ( aTransferable.isDataFlavorSupported( DataFlavor.javaFileListFlavor ) ) {
System.out.println("File list flavor");
List<File> file_list = ( List<File> ) aTransferable.getTransferData( DataFlavor.javaFileListFlavor );
System.out.println( "file_list = " + file_list );
}
if ( URI_LIST_FLAVOR != null && aTransferable.isDataFlavorSupported( URI_LIST_FLAVOR ) ){
System.out.println("URI list flavor");
String uri_list = ( String ) aTransferable.getTransferData( URI_LIST_FLAVOR );
System.out.println( "uri_list = " + uri_list );
}
} catch ( UnsupportedFlavorException e ) {
throw new RuntimeException( e );
} catch ( IOException e ) {
throw new RuntimeException( e );
}
return true;
}
@Override
public boolean canImport( JComponent comp, DataFlavor[] transferFlavors ) {
return true;
}
};
}
}
JDK 1.7.01 上的结果输出
Resulting output on JDK 1.7.01
File list flavor
file_list = []
URI list flavor
uri_list = http://www.google.com
JDK1.6.0.18 上的结果输出
Resulting output on JDK1.6.0.18
URI list flavor
uri_list = http://www.google.com
我可以轻松地为这个问题创建一个解决方法,但我对更多已知的差异和/或关于这些差异的文档更感兴趣.
I can easily create a workaround for this issue, but I am more interested in any more know differences and/or documentation about those differences.
编辑
一些进一步的调查/谷歌搜索让我认为 JDK7 上的行为是创建 URI 和文件列表数据风格,并在可传输中提供它们.然后文件列表只包含代表文件的 URI.因此,仅拖放 URL 时,文件列表为空.我在 JDK 源代码中找不到这个,因为似乎可传输/传输数据是用本机代码创建的(或者至少是我找不到源代码的代码).在 OpenJDK 邮件列表上有一个关于 类似问题的讨论,包含以下引用
Some further investigation/googling makes me think the behavior on JDK7 is to create both the URI and filelist data flavor and offering them both in the transferable. The filelist then only contains the URI's which represent a file. Hence when only drag-and-dropping an URL, the file list is empty. I cannot find this in the JDK source code as it seems the transferable/transferdata is created in native code (or at least code for which I do not find the sources). On the OpenJDK mailing list there was a discussion about a similar issue, containing the following quote
如果您将文件列表从本机拖到 Java 中,应用程序会同时看到 URI 列表和文件列表.如果你拖入一个 URI 列表,它会看到一个 URI 列表,如果所有 URI 都是文件,那么它也是一个非空文件列表,否则只是一个空文件列表.
If you drag a file list from native into Java, the application sees both a URI list and a file list. If you drag in a URI list it sees a URI list, and if all URIs are files also a non-empty file list, otherwise just an empty file list.
编辑2
根据 serg.nechaev 的回答,我在 32/64 位 Linux 系统和几个 Windows 系统(从 XP 到 Windows7)上进行了更多测试.在带有 JDK7 的 Linux 上,我总是得到 URI 数据风格,以及空文件列表风格.在 Windows 上,我得到一个 URI 数据风格和一个非空文件列表数据风格.似乎在临时目录中创建了一个 .URL
文件,并且这也是在文件列表数据风格中传递的,这在 JDK 6 上不是这种情况.
Based on the answer of serg.nechaev I performed some more tests on 32/64 bit Linux systems and several Windows system (ranging from XP to Windows7). On Linux with JDK7 I always get the URI dataflavor, combined with an empty filelist flavor. On Windows, I get a URI dataflavor and a non-empty filelist data flavor. It seems a .URL
file gets created in the temp dir, and this is passed in the filelist data flavor as well, which wasn't the case on JDK 6.
所有这些情况的解决方案是首先检查 URI 数据风格,然后使用文件列表数据风格作为后备
Solution in all these cases is to check for the URI dataflavor first, and use the file list data flavor as fall-back
推荐答案
我认为导致此行为的更改在 $(JDK)/jre/lib/flavormap.properties:
I think the change that caused this behaviour is in $(JDK)/jre/lib/flavormap.properties:
http://hg.openjdk.java.net/jdk7/hotspot-gc/jdk/diff/fd5bf5955e37/src/windows/lib/flavormap.properties
但是,使用您的示例并从您的帖子中拖动到 Google 的链接,我得到了文件列表和WinXP、FireFox 8 上 JDK 1.7.0 上的 uri 列表:
However, using your sample and dragging a link to Google from your post, I am getting both file list & uri list on JDK 1.7.0 on WinXP, FireFox 8:
File list flavor
file_list = [C:DOCUME~1SERGNLOCALS~1Temphttpwww.google.com.URL]
URI list flavor
uri_list = http://www.google.com/
这可能是 JDK 1.7.01 的特定于平台的错误,您可能需要进一步调查,并可能向 Oracle 提交错误.
That could be a platform-specific bug for JDK 1.7.01, you might want to investigate it further and maybe submit a bug to Oracle.
这篇关于JDK1.6和JDK1.7的拖放区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!