[英]Drag and drop differences between JDK1.6 and JDK1.7
有沒有人知道JDK1.6和JDK1.7之間的拖放行為的差異? 將URL從瀏覽器拖放到需要支持JDK1.5,JDK1.6和JDK1.7的應用程序時,我遇到了不同(如下圖所示)。 我現在想知道是否存在其他差異以及是否在某處記錄了這些差異。
我遇到的不同行為是通過點擊並拖動URL到Java應用程序來拖放來自瀏覽器(而不是來自地址欄但來自頁面)的URL。 在JDK1.6上,Transferable不支持DataFlavor.javaFileListFlavor
,而且它支持JDK1.7(盡管在請求傳輸數據時會得到一個空列表)。 以下代碼說明了該問題。 它打開一個JFrame
,您可以在其上拖放像http://www.google.com這樣的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;
}
};
}
}
結果輸出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和文件列表數據的味道,並在transferable中提供它們。 然后,文件列表僅包含表示文件的URI。 因此,當只拖放URL時,文件列表為空。 我在JDK源代碼中找不到這個,因為似乎transferable / transferdata是在本機代碼中創建的(或者至少是我找不到源代碼的代碼)。 在OpenJDK郵件列表上有一個關於類似問題的討論,包含以下引用
如果將文件列表從本機拖到Java中,則應用程序會同時看到URI列表和文件列表。 如果你在URI列表中拖動,它會看到一個URI列表,如果所有URI都是非空文件列表的文件,否則只是一個空文件列表。
EDIT2
根據serg.nechaev的回答,我在32/64位Linux系統和幾個Windows系統(從XP到Windows7)上進行了一些測試。 在使用JDK7的Linux上,我總是得到URI dataflavor,並結合空文件列表的味道。 在Windows上,我獲得了URI dataflavor和非空文件列表數據風格。 似乎.URL
文件是在temp目錄中創建的,並且這也在文件列表數據風格中傳遞,而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提交錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.