Estoy haciendo un programa de Java, y una forma de cargar archivos es arrastrar el archivo a la ventana de la aplicación (swing). Tengo un código que funciona en Windows y Linux. Funciona en OS X, pero el primer archivo que arrastro arroja una excepción, y luego el resto funciona bien.Java arrastrar y soltar en Mac OS X
Aquí está el código que uso para habilitar DnD.
/*
* Allow a file to be opened by dragging it onto the window
*/
public void drop(DropTargetDropEvent dtde){
try {
// Get the object to be transferred
Transferable tr = dtde.getTransferable();
DataFlavor[] flavors = tr.getTransferDataFlavors();
// If flavors is empty get flavor list from DropTarget
flavors = (flavors.length == 0) ? dtde.getCurrentDataFlavors() : flavors;
// Select best data flavor
DataFlavor flavor = DataFlavor.selectBestTextFlavor(flavors);
// Flavor will be null on Windows
// In which case use the 1st available flavor
flavor = (flavor == null) ? flavors[0] : flavor;
// Flavors to check
DataFlavor Linux = new DataFlavor("text/uri-list;class=java.io.Reader");
DataFlavor Windows = DataFlavor.javaFileListFlavor;
// On Linux (and OS X) file DnD is a reader
if(flavor.equals(Linux)) {
dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
BufferedReader read = new BufferedReader(flavor.getReaderForText(tr));
// Remove 'file://' from file name
String fileName = read.readLine().substring(7).replace("%20"," ");
// Remove 'localhost' from OS X file names
if(fileName.substring(0,9).equals("localhost")) {
fileName = fileName.substring(9);
}
read.close();
dtde.dropComplete(true);
System.out.println("File Dragged:" + fileName);
mainWindow.openFile(fileName);
}
// On Windows file DnD is a file list
else if(flavor.equals(Windows)) {
dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
@SuppressWarnings("unchecked")
List<File> list = (List<File>)tr.getTransferData(flavor);
dtde.dropComplete(true);
if(list.size() == 1) {
System.out.println("File Dragged: " + list.get(0));
mainWindow.openFile(list.get(0).toString());
}
} else {
System.err.println("DnD Error");
dtde.rejectDrop();
}
}
//TODO: OS X Throws ArrayIndexOutOfBoundsException on first DnD
catch(ArrayIndexOutOfBoundsException e){
System.err.println("DnD not initalized properly, please try again.");
} catch(IOException e){
System.err.println(e.getMessage());
} catch(UnsupportedFlavorException e){
System.err.println(e.getMessage());
} catch (ClassNotFoundException e){
System.err.println(e.getMessage());
}
}
Por alguna razón, OS X, se emite una ArrayIndexOutOfBoundsException en esta línea:
flavor = (flavor == null) ? flavors[0] : flavor;
Después de que se lanza una excepción, si arrastro otro archivo en la ventana, funciona. ¿Por qué arroja una excepción?
NOTA: mainWindow.openFile() es una función que abre un archivo. Toma un parámetro de cadena (el nombre del archivo) y el programa abre ese archivo.
NOTA 2: Esto está en OS X 10.6.2 (Snow Leopard).
Eso sólo puede significar que los sabores en ese punto no contiene ningún registro. ¿Verificaste si getTransferDataFlavors() o getCurrentDataFlavors() devuelve algo en el primer arrastrar/soltar? – jitter
Bueno, sabores [0] me está dando una excepción fuera de límites. Compruebo si tr.getTransferDataFlavors() tiene una longitud cero, si lo hago, uso dtde.getCurrentDataFlavors() en su lugar. Entonces, aparentemente, dtde.getCurrentDataFlavors() tiene una longitud cero, que es lo que está causando la excepción de fuera de límites. –
Tal vez si trato de obtener los DataFlavors en el evento dragEnter, no serán nulos cuando se desencadene el evento drop. –