2012-01-17 13 views
7

Tengo una aplicación swing en la que me gustaría importar un archivo externo arrastrando el archivo externo desde el explorador de Windows a la aplicación. Tengo esta funcionalidad básica funcionando. Sin embargo, me gustaría cambiar el icono predeterminado del cursor arrastrar/soltar en un cursor apropiado para la aplicación. No he podido cambiar el cursor visible para el usuario mientras se presiona la tecla del mouse y se mantiene sobre la aplicación. He visto ejemplos de esto funcionando si la operación de arrastrar y soltar está dentro de la misma aplicación de oscilación. Intenté lograr esto utilizando DragGestureListener y DragSource sin ningún resultado. Parece que esos métodos no se invocan a menos que la fuente de arrastre esté dentro del balanceo. ¿Es posible cambiar el cursor de arrastre al arrastrar un archivo externo a una aplicación de swing?Establecer cursor personalizado al arrastrar archivo externo a la aplicación Swing

Consulte este ejemplo simplificado:

public class DnDTemplate extends JFrame { 

private static final long serialVersionUID = 1L; 
private JComponent thePane = null; 
private Cursor dropCursor = null; 

public DnDTemplate() { 
    super("Drop File Here"); 

    thePane = (JComponent) getContentPane(); 
    thePane.setTransferHandler(new DndTransferHandler()); 

    ImageIcon imageIcon = new ImageIcon("drop_here.gif"); 
    Image image = imageIcon.getImage();  
    BufferedImage bufferedImage = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB); 
    Graphics graphics = bufferedImage.getGraphics(); 
    graphics.drawImage(image, 0, 0, null); 
    dropCursor = Toolkit.getDefaultToolkit().createCustomCursor(bufferedImage, new Point(16, 16), "drop cursor"); 

    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    setSize(300, 300); 
} 

public static void main(String[] args) { 
    new DnDTemplate().setVisible(true); 
} 

class DndTransferHandler extends TransferHandler { 

    private static final long serialVersionUID = 1L; 

    @Override 
    public boolean canImport(TransferHandler.TransferSupport info) { 
     // This gets called repeatedly while dragged file is over frame 
     if (!info.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { 
      return false; 
     } 
     // Even though this method is called at the appropriate time, 
     // setting the cursor here is of no consequence 
     info.getComponent().setCursor(dropCursor); 

     return true; 
    } 

    @Override 
    public boolean importData(TransferHandler.TransferSupport info) { 
     // this gets called when file is dropped 
     if (!info.isDrop()) { 
      return false; 
     } 

     Transferable transferable = info.getTransferable(); 
     String importFileName = null; 
     try { 
      List<File> fileList = (List<File>) transferable.getTransferData(DataFlavor.javaFileListFlavor); 
      Iterator<File> iterator = fileList.iterator(); 
      while (iterator.hasNext()) { 
       File f = iterator.next(); 
       importFileName = f.getAbsolutePath(); 
      } 
      info.getComponent().setCursor(dropCursor); 
      thePane.setCursor(dropCursor); 

     } catch (Exception e) { 
      return false; 
     } 

     System.out.println("Importing " + importFileName); 
     // Return the cursor back to the default 
     thePane.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 
     return true; 
    } 

} 

}

+6

No, esto no respondió la pregunta. Vi eso anterior e intenté usar el setDropTarget. El método dragEnter se llama en el momento apropiado, pero el cursor se mantiene como el icono predeterminado de arrastrar/soltar y no cambiará al que he especificado. – agility

+0

Intenté colocar el cursor en dragOver y experimenté el parpadeo mencionado en http://bugs.sun.com/view_bug.do?bug_id=4451328. Puede ser que no esté arreglado después de todo. – tenorsax

Respuesta

1

responsabilidad: esto debería haber sido un comentario y no una respuesta, pero es demasiado largo para caber en los comentarios. Eliminaré esta respuesta si es completamente incorrecta

No probé esto, pero mirando la API de TransferHandler sugiero echar un vistazo al método TransferHandler#getDragImage.

La documentación no está muy clara sobre si esta imagen se utiliza cuando se inicia el arrastre del componente para el que se configuró el TransferHandler, o si se inicia un arrastre desde fuera de la aplicación y el cursor sobrepasa el componente para el cual se establece TransferHandler. He encontrado an example que parece sugerir esto ciertamente trabaja en aplicaciones Java, pero todavía no son concluyentes acerca de arrastrar y soltar procedente de una aplicación externa

Bug ID 4816922 sugiere utilizar el TransferHandler#getVisualRepresentation pero no está claro si el error ya está fijado.

+2

Aunque debería haber especificado en mi pregunta, estoy buscando una solución en Java 6. Esto solo se implementa en Java 7. Además, al probar esta solución con TransferHandler.setDragImage, la llamada parece ignorada y aparece el icono de arrastrar lo mismo con y sin la llamada a setDragImage. – agility

Cuestiones relacionadas