Drag-And-Drop Aplicações
Swing em Java – Parte 04
Aprenda
a usar as classes de Drag-and-Drop do Java Swing através de um exemplo prático.
Por: Francisco Voccio Netto
Lado Drop
Por outro lado, temos a face Drop,
que será chamada quando o usuário soltar o botão do mouse.
Para que isso se concretize precisamos desenvolver uma classe que implemente a
interface DropTargetListener.(Listagem 4).
Listagem 4. OuvinteDragSource.java
package
br.javamagazine.dnd;
import java.awt.*;
import br.javamagazine.botoes.BotaoImpl;
import br.javamagazine.figuras.Figura;
import br.javamagazine.telas.util.PainelContainer;
public class OuvinteLocalDrop implements DropTargetListener {
private PainelContainer painelContainer;
private GerenciadorDeTransferencia gerenciador;
public OuvinteLocalDrop(PainelContainer painelContainer) {
this.painelContainer =
painelContainer;
gerenciador = new GerenciadorDeTransferencia();
}
/**
* Chamado pelo isDragOk
* Verifica se a ação do drop é válida
* @param DropTargetDragEvent o evento
* @return retorna a condição
*/
private boolean
isDragFlavorSupported(DropTargetDragEvent e) {
boolean ok = false;
if
(e.isDataFlavorSupported(GerenciadorDeTransferencia.localStringFlavor)) {
ok = true;
}
else if (e.isDataFlavorSupported(DataFlavor.stringFlavor))
{
ok = true;
}
return ok;
}
/**
* É chamado pelo dragEnter e o dragOver
* Também é verificado a ação e as operações
* @param O evento drop
* @return Retorna verdadeiro se o movimento de arrastar
* está correto
*/
private boolean
isDragOk(DropTargetDragEvent e) {
if (isDragFlavorSupported(e)
== false) { return false; }
int da = e.getDropAction();
// verifica a ação que a area de resposta pode receber
if ((da & this.painelContainer.obterAcceptableActions()) == 0) {
return false; }
return true;
}
/**
* Por onde o evento de arrastar começa
* chama o acceptDrag ou rejectDrag com base no isDragOk
*/
public void
dragEnter(DropTargetDragEvent e) {
if (isDragOk(e) == false) {
e.rejectDrag();
return;
}
e.acceptDrag(e.getDropAction());
}
/**
* Depois que o objeto é arrastado
* chama o acceptDrag ou rejectDrag com base no isDragOk
*/
public void dragOver(DropTargetDragEvent
e) {
if (isDragOk(e) == false) {
this.painelContainer.mudarCorBorda(Color.RED);
e.rejectDrag();
return;
}
}
public void
dropActionChanged(DropTargetDragEvent e) {
if (isDragOk(e) == false) {
e.rejectDrag();
return;
}
e.acceptDrag(e.getDropAction());
}
public void
dragExit(DropTargetEvent e) {
}
public void
drop(DropTargetDropEvent e) {
DataFlavor escolha = gerenciador.obterNossaOpcao();
if (escolha == null) {
e.rejectDrop();
return;
}
if ((e.getSourceActions()
& this.painelContainer.obterAcceptableActions()) == 0)
{
e.rejectDrop();
return;
}
BotaoImpl botao = null;
try {
e.acceptDrop(this.painelContainer.obterAcceptableActions());
botao = (BotaoImpl)
e.getTransferable().getTransferData(escolha);
if (botao == null) { throw new NullPointerException(); }
}
catch (Throwable t) {
e.dropComplete(false);
return;
}
// utiliza a fabrica de figuras conforme o botão selecionado
Figura figura = botao.obterFigura();
painelContainer.adicionarFigura(figura, e.getLocation());
}
}
Esta é uma implementação simples da interface DropTargetListener, todos os métodos são disponibilizados pela API. O que
mais chama a nossa atenção é o método drop
pois é
ele que é responsável por definir o estado da aplicação após o usuário soltar o
botão do mouse.
Reparem que eu chamo novamente nosso gerenciador e obtenho nossa escolha (flavor) como foi definido anteriormente.
Temos também um atributo painelContainer, este como foi definido pelo
construtor da nossa classe é o local de destino do nosso objeto que foi
arrastado.
Mostrarei uma pequena parte da implementação de como ficará nossa classe
PainelContainer (Listagem 5).
Listagem 5. PainelContainer.java
package br.javamagazine.telas.util;
import java.awt.*;
import java.awt.dnd.*;
import javax.swing.JComponent;
import br.javamagazine.dnd.OuvinteLocalDrop;
import br.javamagazine.figuras.Figura;
public abstract class PainelContainer extends JComponent {
//todas as inicializações das propriedades (vide
projeto)
private int acceptableActions;
public PainelContainer() {
this.acceptableActions =
DnDConstants.ACTION_COPY_OR_MOVE;
// component, ops, listener, accepting
new DropTarget(this,
this.acceptableActions, new OuvinteLocalDrop(this),
true);
}
public abstract void adicionarComponenteDrag(Figura figura, Point
localizacao);
public abstract Boolean removerComponenteDrag(Figura figura);
.
. //continuação
da classe
.
É importante
ressaltar esta parte da implementação, pois por decisão minha defini que esta
classe será do tipo JComponent ou seja, nosso editor final irá herdar desta
classe.
Toda estrutura do exemplo pode ser observada na Figura 1.
Outra decisão são os métodos abstratos adicionarComponenteDrag e removerComponenteDrag, sendo
assim, quem for estender (no nosso caso o Editor) implementará da forma mais
conveniente ( será mostrado em seguida Listagem
6).