Drag and Drop (Arrastrar y Soltar)

De ChuWiki

Conceptos generales

  • Un objeto entre aplicaciones se puede pasar, principalmente, de dos formas
    • Arrastrarlo de un origen hasta un destino
    • Copiarlo al portapapeles desde un origen y pegarlo desde el portapapeles en un destino
  • Ambas posibilidades necesitan envolver el dato en cuestión en un objeto que implemente Transferable
    • El dato se encapsula en un Transferable
    • Mediante la clase DataFlavor se indica a que tipos de datos se puede convertir ese Transferable
      • Un fichero se puede querer desenvolver como un tipo File para un explorador de ficheros,
      • o como un tipo String con el nombre del fichero para meter en un campo de texto...
  • En windows, al arrastrar, se puede realizar tres acciones según se pulsen las teclas SHIFT o CONTROL
    • Se copia un objeto si al soltar, está pulsada la tecla CONTROL
    • Se mueve un objeto si al soltar, está pulsada la tecla SHIFT
    • Se enlaza un objeto si al soltar, están pulsadas las teclas SHIFT y CONTROL

Creando nuestro propio Transferable...

  • Java proporciona una clase: StringSelection que implementa esta interfaz cuando el dato envuelto es un String
  • Basicamente se trata de guardar una instancia del dato y de proporcionar informacion sobre las clases a las que se puede convertir
  • DataFlavor es la clase que se usa para realizar esta labor
  • Se construye con un cadena de la siguiente forma: "tipo MIME;class=paquete.claseJava"
  • Por defecto, están definidos como estáticos varios tipos en DataFlavor
    • DataFlavor.imageFlavor
    • DataFlavor.stringFlavor
    • DataFlavor.javaJVMLocalObjectMimeType
    • DataFlavor.javaRemoteObjectMimeType
    • DataFlavor.javaSerializedObjectMimeType
  • Por ejemplo, DataFlavor.imageFlavor es: new DataFlavor("image/x-java-image;class=java.awt.Image")
  • Aqui se puede ver un ejemplo de como se implementaría un transferable para una imagen.ImageSelection.java

Arrastrando y soltando en AWT...

Un par de conceptos...

  • El origen del arrastre es un objeto de la clase DragSource
  • El destino al soltar es un objeto de tipo DropTarget
  • Tanto origen como destino tienen unos listener asociados a los que indican que está ocurriendo en cada momento
  • Se notifican cosas como que el ratón ha abandonado el origen de arrastre, ha entrado en el destino de soltar...
  • Al destino y al origen se le asocian elementos de la interfaz gráfica que heredan de Component
  • Además en el caso de arrastrar existe una clase DragGestureListener que decide si lo que hace el usuario se debe interpretar como arrastrar o no

Un diagrama con las clases que intervienen en el asunto...

Un ejemplo sencillo de como se implementaria...

Las clases para arrastrar

Las clases para soltar

Arrastrando y soltando en Swing...

  • Swing simplifica el proceso de arrastrar y soltar/copiar y pegar
  • Para que un componente Swing sea fuente de arrastre hay que llamar al metodo setDragEnabled(true)
  • Se siguen usando las mismas clases Transferable/DataFlavor, pero se facilita su uso mediante un TransferHandler
  • A un componente Swing se le pude decir que use un determinado TransferHandler
  • El TransferHandler se encarga de escribir y leer el dato en el Transferable
  • Un componente Swing tiene un unico TransferHandler
  • Se puede crear asi: new TransferHandler("propiedad") y automaticamente se invoca al setPropiedad(...)/getPropiedad() del componente con el dato contenido en el Transferable
  • Se puede crear un manejador de transferencia específico, heredando de la clase TransferHandler y redefiniendo los métodos necesarios
    • Se puede ver un ejemplo de un JLabel con un nuevo TransferHandler que acepta, color, texto e imagenes en TransferHandlerJLabel.java

Usando el portapapeles...

  • El uso del portapapeles es sencillo: consiste en escribir o leer de el un Transferable
  • Para obtener el portapapeles del sistema (visible por otras aplicaciones, incluidas nativas)
    • Clipboard clipboard = Toolkit.getDefaultToolkit( ).getSystemClipboard( );
  • Para obtener un portapapeles local
    • Clipboard clipboard = new Clipboard("nombre de nuestro portapapeles");
  • Para escribir algo en el portapapeles
    • clipboard.setContents(imageSelected, clipboardOwner);
    • ClipboardOwner es un listener para que se nos avise si el contenido del portapapeles cambia (si alguien ha escrito en el), puede ser null
  • Para leer algo del portapapeles
    • Transferable transferable = clipboard.getContents( null );
  • Aqui se puede ver un ejemplo de como se trabaja con el portapapeles usando el transferable anteriormente creado.Portapapeles.java


Finalmente un zip (java 6.0) con todas las clases de los ejemplos dnd.zip