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

发布于 2024-12-24 02:08:52 字数 4292 浏览 2 评论 0 原文

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

我遇到的不同行为是通过单击并将 URL 从浏览器(不是从地址栏而是从页面)拖放到 Java 应用程序上。在 JDK1.6 上,Transferable 不支持 DataFlavor.javaFileListFlavor,而在 JDK1.7 上则支持(尽管在请求其传输数据时您会得到一个空列表)。下面的代码说明了这个问题。它会打开一个 JFrame,您可以在其中拖放 URL,例如 http://www。 google.com 并打印出它是使用文件列表风格还是 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;
      }
    };
  }
}

JDK 1.7.01 上的结果输出

File list flavor
file_list = []
URI list flavor
uri_list = http://www.google.com

JDK1.6.0.18 上的结果输出

URI list flavor
uri_list = http://www.google.com

我可以轻松地为这个问题创建一个解决方法,但是我更感兴趣了解更多差异和/或有关这些差异的文档。

编辑

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

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

Edit2

基于serg.nechaev的回答,我在32/64位Linux系统和几个Windows系统(从XP到Windows7)上进行了一些更多的测试。在使用 JDK7 的 Linux 上,我总是获得 URI 数据风格,以及空文件列表风格。在 Windows 上,我获得 URI 数据风格和非空文件列表数据风格。似乎在临时目录中创建了一个 .URL 文件,并且该文件也在文件列表数据风格中传递,而 JDK 6 上的情况并非如此。

所有这些情况下的解决方案是检查首先针对 URI 数据风格,然后使用文件列表数据风格作为后备

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.

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

Resulting output on JDK 1.7.01

File list flavor
file_list = []
URI list flavor
uri_list = http://www.google.com

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.

Edit

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

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.

Edit2

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.

Solution in all these cases is to check for the URI dataflavor first, and use the file list data flavor as fall-back

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

蝶…霜飞 2024-12-31 02:08:52

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

http://hg.openjdk.java.net/jdk7/hotspot-gc/jdk/diff/fd5bf5955e37/src/windows/lib/flavormap.properties

但是,使用您的示例并拖动从你的帖子到谷歌的链接,我得到了文件列表和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 提交错误。

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

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~1\SERGN\LOCALS~1\Temp\httpwww.google.com.URL]
URI list flavor
uri_list = http://www.google.com/

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文