Java JDK1.6和JDK1.7之间的拖放差异

Java JDK1.6和JDK1.7之间的拖放差异,java,swing,drag-and-drop,java-7,Java,Swing,Drag And Drop,Java 7,有人知道JDK1.6和JDK1.7之间拖放行为的差异吗?在将URL从浏览器拖放到需要支持JDK1.5、JDK1.6和JDK1.7的应用程序时,我遇到了一个不同之处(如下所示)。我现在想知道是否还存在其他差异,是否有记录在案 我遇到的不同行为是,通过单击并将URL拖动到Java应用程序,从浏览器(不是从地址栏而是从页面)拖放URL。在JDK1.6上,Transferable不支持DataFlavor.javaFileListFlavor,而在JDK1.7上它支持(尽管在请求其传输数据时,您会得到一

有人知道JDK1.6和JDK1.7之间拖放行为的差异吗?在将URL从浏览器拖放到需要支持JDK1.5、JDK1.6和JDK1.7的应用程序时,我遇到了一个不同之处(如下所示)。我现在想知道是否还存在其他差异,是否有记录在案

我遇到的不同行为是,通过单击并将URL拖动到Java应用程序,从浏览器(不是从地址栏而是从页面)拖放URL。在JDK1.6上,Transferable不支持
DataFlavor.javaFileListFlavor
,而在JDK1.7上它支持(尽管在请求其传输数据时,您会得到一个空列表)。下面的代码说明了该问题。它会打开一个
JFrame
,您可以在其上拖放类似的URL,并打印出它使用的是文件列表风格还是URI列表风格

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;
      }
    };
  }
}
JDK1.6.0.18上的结果输出

URI list flavor
uri_list = http://www.google.com
我可以很容易地为这个问题创建一个解决方案,但我更感兴趣的是了解更多的差异和/或关于这些差异的文档

编辑

一些进一步的调查/谷歌搜索让我认为JDK7上的行为是创建URI和文件列表数据风格,并以可转换的方式提供它们。然后,文件列表只包含表示文件的URI。因此,当仅拖放URL时,文件列表为空。我在JDK源代码中找不到这一点,因为transferable/transferdata似乎是在本机代码中创建的(或者至少是我找不到源代码的代码)。在OpenJDK邮件列表中有一个关于a的讨论,包含以下引用

如果将文件列表从本机拖动到Java中,应用程序将同时看到URI列表和文件列表。如果拖动一个URI列表,它会看到一个URI列表,如果所有URI都是文件,那么它也是一个非空文件列表,否则它只是一个空文件列表

Edit2

根据serg.nechaev的回答,我在32/64位Linux系统和几个Windows系统(从XP到Windows7)上进行了更多的测试。在使用JDK7的Linux上,我总是获得URI dataflavor,并结合一个空文件列表。在Windows上,我得到一个URI dataflavor和一个非空文件列表数据flavor。似乎在temp dir中创建了一个
.URL
文件,该文件也在filelist数据风格中传递,而在JDK 6上则不是这样


在所有这些情况下,解决方案都是首先检查URI dataflavor,并使用文件列表数据flavor作为回退

我认为导致此行为的更改在$(JDK)/jre/lib/flavormap.properties中:

然而,使用您的示例并从您的帖子中拖拽到Google的链接,我得到了WinXP FireFox 8上JDK 1.7.0上的文件列表和uri列表:

File list flavor
file_list = [C:\DOCUME~1\SERGN\LOCALS~1\Temp\httpwww.google.com.URL]
URI list flavor
uri_list = http://www.google.com/

这可能是JDK 1.7.01的一个特定于平台的错误,您可能希望进一步调查它,并可能向Oracle提交一个错误。

Java 7应该支持其他功能。如果您可以在Java6中做一些事情,那么在Java7中就做不到,因为这很可能是一个bug。我将编写支持Java6的代码,它也将与Java7一起工作。如果你说你想知道Java7的每一个新特性,因此你决定是否使用该特性,那么你可能是第一个创建这样一个列表的人。您可能需要比较两个版本之间的源代码。顺便说一句,Java6Update30可能对Java7的一些特性进行了后置移植。然而,在Java7中,我也得到了一个文件列表,这打破了我的应用程序中的代码,它是一个if-else if-else构造,覆盖了所有数据类型。所以现在它进入了代码的文件列表风格分支,由于文件列表是空的,所以没有导入我的数据。我还没有在WinXP上检查,但我今天将测试它,并让您知道我是否有相同的问题。
File list flavor
file_list = [C:\DOCUME~1\SERGN\LOCALS~1\Temp\httpwww.google.com.URL]
URI list flavor
uri_list = http://www.google.com/