2008年1月2日水曜日

Java6 JTree DnD Test(ドラッグアンドドロップテスト)

ugnagさんの解説を元に作成しました。

1.ドラッグを許可します。
2.トランスファハンドラを設定します。
3.転送データを作成します。
4.アクションを返します。
5.ドロップ可能かどうかを返します。
6.ドロップされたデータを受け取ります。
7.ドロップ完了後の処理をします。



import java.awt.BorderLayout;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JTree;
import javax.swing.TransferHandler;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;

/**
* Java6 JTree DnD Test
* Java6 JTree ドラッグアンドドロップテスト
* http://ugnag.lar.jp/pgm/java/dd/index.html
* ※ugnagさんの解説を元に作成しました。
*/
public class JTreeDnDTest {

/**
* @param args
*/
public static void main(String[] args) {
JFrame f = new JFrame();
JTree t = new MyTree3();
JTree t2 = new MyTree3();
f.add(t, BorderLayout.CENTER);
f.add(t2, BorderLayout.EAST);
f.setSize(200, 200);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}

class MyTree3 extends JTree {
public MyTree3() {
super();
init();
}

private void init() {
// 1.ドラッグを許可します。
setDragEnabled(true);
// 2.トランスファハンドラを設定します。
setTransferHandler(new TreePathTransferHandler());
}
}
/**
* ツリーパストランスファハンドラ
*
*/
class TreePathTransferHandler extends TransferHandler {
@Override
protected Transferable createTransferable(JComponent c){
// 3.転送データを作成します。
if (c instanceof JTree) {
JTree tree = (JTree)c;
TreePath[] paths = tree.getSelectionPaths();

return new TreePathTransferable(paths);
}
return null;
}
@Override
public int getSourceActions(JComponent c) {
// 4.アクションを返します。
// 今回は無条件にMOVEとする。
return MOVE;
}
@Override
public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
// 5.ドロップ可能かどうかを返します。
// 受け入れ判定をせずに、無条件でTRUE。FALSEを返すと、UIでドロップ禁止となる。
return true;
}
/**
* 出力側のドロップ完了処理。
* actionがMOVEの場合、ツリーを削除します。
* ※importDataがfalseを返した場合、actionはNONEになります。
*/
@Override
protected void exportDone(JComponent source, Transferable data,
int action) {
// 7.ドロップ完了後の処理をします。
if (!(source instanceof JTree)) {
return;
}
JTree tree = (JTree)source;
if (action == MOVE) {
for (DataFlavor df : data.getTransferDataFlavors()) {
try {
TreePath[] patha = (TreePath[]) data.getTransferData(df);
TreePath path = patha[0];
Object oo = path.getLastPathComponent();
DefaultMutableTreeNode node = (DefaultMutableTreeNode)oo;
node.removeFromParent();
((DefaultTreeModel)tree.getModel()).reload();
} catch (UnsupportedFlavorException e) {
e.printStackTrace();
throw new RuntimeException(e);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
} else {
super.exportDone(source, data, action);
}
}
/**
* 入力側のドロップ処理。
* ドロップされたノードに、ドラッグされたノードを追加します。
*/
@Override
public boolean importData(JComponent comp, Transferable t) {
// 6.ドロップされたデータを受け取ります。
if (!(comp instanceof JTree)) {
return false;
}
JTree tree = (JTree)comp;
javax.swing.JTree.DropLocation loc = tree.getDropLocation();
TreePath path = loc.getPath();
DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
DataFlavor[] dfa = t.getTransferDataFlavors();
for (DataFlavor df : dfa) {
try {
TreePath[] orgPathA = (TreePath[])t.getTransferData(df);
for (TreePath orgPath : orgPathA) {
DefaultMutableTreeNode oNode = (DefaultMutableTreeNode)orgPath.getLastPathComponent();
node.add(oNode);
}
((DefaultTreeModel)tree.getModel()).reload();
return true;
} catch (UnsupportedFlavorException e) {
e.printStackTrace();
throw new RuntimeException(e);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}

}
return true;
}
}

/**
* ツリーパス用トランスファエイブル
* ツリーパスの配列と、データフレーバーの配列を持つ。
* http://ugnag.lar.jp/docs/java/dd/index.html
* ※ugnagさんのコードをほぼそのまま利用しています。
*/
class TreePathTransferable implements Transferable
{
TreePath[] paths;
// データフレーバ(フレーバ=食品への風味付け)
DataFlavor[] dflv;

public TreePathTransferable(TreePath[] paths){
this.paths = paths;
dflv = new DataFlavor[]{new DataFlavor(TreePath[].class, "array of TreePath")};
}
@Override
public Object getTransferData(DataFlavor flavor){
for (DataFlavor df : dflv) {
if (df.getMimeType().equals(flavor.getMimeType())){
if (df.getClass().equals(flavor.getClass())){
return paths;
}
}
}
return null;
}
@Override
public DataFlavor[] getTransferDataFlavors(){
return dflv;
}
@Override
public boolean isDataFlavorSupported(DataFlavor flavor){
DataFlavor[] flv = getTransferDataFlavors();
for(int i = 0 ; i < flv.length ; i++){
if(flv[i].equals(flavor)){
return true;
}
}
return false;
}
}



1.ドラッグを許可します。

2.トランスファハンドラを設定します。

3.転送データを作成します。
ドラッグ操作を契機に呼び出されます。

4.アクションを返します。
NONE,COPY,MOVE,COPY_OR_MOVE,LINKの5種類があります。
NONE,COPY,MOVEまではいいとして、COPY_OR_MOVE,LINKが謎です。

5.ドロップ可能かどうかを返します。
ドロップ可能な場合TRUE。ドロップ不可の場合FALSEを返します。
FALSEを返すと、マウスカーソルが車両通行止めになります。

6.ドロップされたデータを受け取ります。
3.で作成したデータを受け取ります。
JTree.getDropLocation().getPath()で、どのツリーパスにドロップされたかが分ります。
今回はドラッグしたツリーを、ドロップされたツリーに追加しています。

7.ドロップ完了後の処理をします。
6.でFALSEを返すと、パラメータのアクションがNONEになります。
今回は、MOVEの場合だけ、ドラッグしたツリーを削除しています。

0 件のコメント: