如何拖动JTree的节点名字至JTextArea中 我最近在学习JTree的用法,需要使用JTree的节点,初步想法是拖动其节点至JTextArea中显示,只需要显示节点名字即可,希望高手们能指点一下,我的mail: [email protected], 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 JTree的节点可以这样拖动的吗?按你的需求应该是把节点的名字复制到JTextArea里面吧。 当你选中节点的时候,你是知道如何去获取节点的名字的。你可以使用快捷菜单去复制,把拿到的值放到一个变量里面去存储。当在JTextArea里面的时候,在通过那个中间变量拿出来设置进去就OK。 不知是否是你所想要的? 拖拽倒是没有什么问题。只是比较麻烦。你可以参考一下api文档中关于dnd的介绍。有点忙,如果你需要我可以写个简单的例子出来。但是需要些时间。 这几天正好做Tree的拖拽自定义Tree extends JTree implements DropTargetListener, DragGestureListener, DragSourceListener /** * 拖开始 数据传递 */ public void dragGestureRecognized(DragGestureEvent e) { InputEvent inputEvent = e.getTriggerEvent(); try { // ②drag位置にTHierarchyTreeNodeが存在しない場合,①.THierarchyTreeNodeがルートノードの場合,処理を終了 Point pt = e.getDragOrigin(); TreePath checkPathCheck = getPathForLocation(pt.x, pt.y); if (checkPathCheck == null || checkPathCheck.getParentPath() == null) { return; } // ①drag位置にあるTHierarchyTreeNode(自定义的节点类)を取得する。 if (SwingUtilities.isLeftMouseButton((MouseEvent) inputEvent)) { if ((e.getDragAction() | DnDConstants.ACTION_COPY_OR_MOVE) != 0) { TreePath path = getLeadSelectionPath(); THierarchyTreeNode node = (THierarchyTreeNode) path.getLastPathComponent(); //取得当前节点和子节点 ArrayList<THierarchyTreeNode> listTreeNode = new ArrayList<THierarchyTreeNode>(); Enumeration enumNode = node.breadthFirstEnumeration(); while (enumNode.hasMoreElements()) { THierarchyTreeNode eachNode = (THierarchyTreeNode) enumNode.nextElement(); listTreeNode.add(eachNode); } // ③ ①.THierarchyTreeNode(继承Transferable,可直接用Transferable)を引数にTTransferableクラスをインスタンス化する TTransferable transfer = new TTransferable(listTreeNode); // ④ドラッグを開始する。 e.startDrag(DragSource.DefaultCopyDrop, transfer, this); } } } catch (InvalidDnDOperationException ioe) { // 処理なし } } /** * ドロップ時に呼ばれるメソッド 転送データを設定する。 */ public void drop(DropTargetDropEvent e) { // 転送をチェック(転送データがTTransferable.nodeFlavor形式でない場合) if (e.isDataFlavorSupported(TTransferable.nodeFavor)) { // ①転送データ:List<THierarchyTreeNode>を取得する。 List<THierarchyTreeNode> list = TTransferable.getTHerarchyTreeNodeList(e.getTransferable()); // ② 転送データが存在しない場合は処理終了 if (list == null || list.isEmpty()) { e.rejectDrop(); return; } // ③drop位置にあるTHierarchyTreeNodeを取得する。ドロップ位置にノードが存在しない場合、処理を終了する。 DefaultTreeModel model = (DefaultTreeModel) getModel(); Point p = e.getLocation(); TreePath targetPath = getPathForLocation(p.x, p.y); if (targetPath == null) { e.dropComplete(false); return; } // 目標ノード THierarchyTreeNode targetNode = (THierarchyTreeNode) targetPath.getLastPathComponent(); TreePath dropPath = new TreePath(((DefaultTreeModel) this.getModel()).getPathToRoot(targetNode));// 目標パス // 自分の親ノード THierarchyTreeNode parentNode = (THierarchyTreeNode) list.get(0).getParent(); // ④ 同コンポーネント内のドラッグ&ドロップがないか、 以下の項目をチェックする。 treeTotree = true; // 親ノードを子ノードにドロップしようとしている場合、処理を終了 TreePath dragPath = new TreePath(((DefaultTreeModel) this.getModel()).getPathToRoot(list.get(0)));// 源パス String strDragPath = dragPath.toString();// 源パス String strDropPath = dropPath.toString();// 目標パス String subDragPath = strDragPath.substring(0, strDragPath.length() - 1); if (strDropPath.startsWith(subDragPath)) { e.dropComplete(false); return; } // 自分に自分をドロップしようとしている場合、処理を終了 if (parentNode.equals(targetNode)) { e.dropComplete(false); return; } if (targetNode.equals(list.get(0))) { e.dropComplete(false); return; } e.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); // ⑤ ③.THierarchyTreeNodeに①.転送データを子ノードとして追加する。 if (parentNode != null) { // tree -> tree // 転送したノードをTreeから削除 model.removeNodeFromParent(list.get(0)); model.insertNodeInto(list.get(0), targetNode, targetNode.getChildCount()); } else { // spread -> tree for (THierarchyTreeNode treeNode : list) { model.insertNodeInto(treeNode, targetNode, targetNode.getChildCount()); } } // 刷新Tree控件 ((DefaultTreeModel) this.getModel()).reload(list.get(0)); // 展開します expandAll(dropPath, true); // 選択 this.setSelectionPath(dropPath); // ⑥ ドロップ処理を完了する。 e.dropComplete(true); } else { e.rejectDrop(); } } /** * 拖放完毕后的处理(正确的释放后的处理) */ public void dragDropEnd(DragSourceDropEvent e) { // ①ドロップが正常に完了したかをチェックする。 if (!e.getDropSuccess()) { return; } // ②転送データ:List<THierarchyTreeNode>を取得する。 List<THierarchyTreeNode> list = TTransferable.getTHerarchyTreeNodeList(e.getDragSourceContext() .getTransferable()); // ②.転送データが存在しない場合は処理終了 if (list == null || list.isEmpty()) { return; } // tree -> spread if (treeTotree == false) { // 転送したノードをTreeから削除 DefaultTreeModel model = (DefaultTreeModel) getModel(); model.removeNodeFromParent(list.get(0)); } else { // tree -> tree return; } // 更新します ((DefaultTreeModel) this.getModel()).reload(); TreePath rootPath = new TreePath(((DefaultTreeModel) this.getModel()).getRoot()); this.setSelectionPath(rootPath); // 展開します expandAll(rootPath, true); // 選択 this.setSelectionPath(rootPath); }以上是树型控件的拖拽, JTextArea中也写类似的拖放代码,即可完成拖拽注:其中有些类是自定义类(因为要传递一些别的数据),可使用它的父类(如:THierarchyTreeNode->TreeNode)即可 哦~~楼上捷足先登了。ls比我考虑的要多,应该是考虑到了可以多选拖拽的情形吧,所以才在transfer里面使用List来存储数据。可是model.removeNodeFromParent(list.get(0));这句又是为何?只删除第一个元素?这个写死了就把前面的灵活性给抹杀了。不过要是lz的要求其实简单的多了,特别在targetListener中的drop处理上。因为如果是树,特别是自拖拽的树有许多的限制条件。例如移动后要添加,成功后要从原来的路径上整个删除直至叶子节点的所选分支……不管怎么说,ls的代码很规范,考虑也比较周全,pf。我的代码分开了五个类,我不愿意都放到一起,看起来很乱。而且由于仓促写的,没有加注释;代码也没有做什么优化和调整。凑合看吧。我就打包发到你邮箱里了。我的代码和楼上的所用到的都是一样的,只是具体处理上有所区别。请结合ls的代码及注释(你能看懂那些日语的大概含义即可) model.removeNodeFromParent(list.get(0)); 这句又是为何?只删除第一个元素?这个写死了就把前面的灵活性给抹杀了。 其实上面的代码只是单选拖拽, 在拖拽父节点时,所对应的子节点也要跟着动,因此用List来存储数据,它存储了拖拽的节点和所有子节点.只删除第一个元素list(0),是因为只要删除了所选择的节点,那么它的子节点也都删除了 Java?先学c!!!!! 接受文件线程~急 请教 c++到java的类型转换问题! JAVA初学者之旅(希望对JAVA初学者学习有帮助) 怎样做到文件关联? 如何把查询的数据表信息显示到JTable中?欢迎您的指教!!! java程序 极度郁闷中,各位高手救命啊!关于数据库查询的古怪问题 没有分了也还问 help 富有挑战性的题目:CVSLIENT 关于 中文文件下载后乱麻问题(800分赠送) java和C#哪个更好入门啊
当你选中节点的时候,你是知道如何去获取节点的名字的。你可以使用快捷菜单去复制,把拿到的值放到一个变量里面去存储。当在JTextArea里面的时候,在通过那个中间变量拿出来设置进去就OK。
不知是否是你所想要的?
有点忙,如果你需要我可以写个简单的例子出来。但是需要些时间。
自定义Tree extends JTree implements DropTargetListener, DragGestureListener, DragSourceListener
/**
* 拖开始 数据传递
*/
public void dragGestureRecognized(DragGestureEvent e) {
InputEvent inputEvent = e.getTriggerEvent();
try {
// ②drag位置にTHierarchyTreeNodeが存在しない場合,①.THierarchyTreeNodeがルートノードの場合,処理を終了
Point pt = e.getDragOrigin();
TreePath checkPathCheck = getPathForLocation(pt.x, pt.y);
if (checkPathCheck == null || checkPathCheck.getParentPath() == null) {
return;
} // ①drag位置にあるTHierarchyTreeNode(自定义的节点类)を取得する。
if (SwingUtilities.isLeftMouseButton((MouseEvent) inputEvent)) {
if ((e.getDragAction() | DnDConstants.ACTION_COPY_OR_MOVE) != 0) {
TreePath path = getLeadSelectionPath();
THierarchyTreeNode node = (THierarchyTreeNode) path.getLastPathComponent();
//取得当前节点和子节点
ArrayList<THierarchyTreeNode> listTreeNode = new ArrayList<THierarchyTreeNode>();
Enumeration enumNode = node.breadthFirstEnumeration();
while (enumNode.hasMoreElements()) {
THierarchyTreeNode eachNode = (THierarchyTreeNode) enumNode.nextElement();
listTreeNode.add(eachNode);
}
// ③ ①.THierarchyTreeNode(继承Transferable,可直接用Transferable)を引数にTTransferableクラスをインスタンス化する
TTransferable transfer = new TTransferable(listTreeNode); // ④ドラッグを開始する。
e.startDrag(DragSource.DefaultCopyDrop, transfer, this);
}
}
} catch (InvalidDnDOperationException ioe) {
// 処理なし
}
} /**
* ドロップ時に呼ばれるメソッド 転送データを設定する。
*/
public void drop(DropTargetDropEvent e) {
// 転送をチェック(転送データがTTransferable.nodeFlavor形式でない場合)
if (e.isDataFlavorSupported(TTransferable.nodeFavor)) {
// ①転送データ:List<THierarchyTreeNode>を取得する。
List<THierarchyTreeNode> list = TTransferable.getTHerarchyTreeNodeList(e.getTransferable()); // ② 転送データが存在しない場合は処理終了
if (list == null || list.isEmpty()) {
e.rejectDrop();
return;
} // ③drop位置にあるTHierarchyTreeNodeを取得する。ドロップ位置にノードが存在しない場合、処理を終了する。
DefaultTreeModel model = (DefaultTreeModel) getModel();
Point p = e.getLocation();
TreePath targetPath = getPathForLocation(p.x, p.y);
if (targetPath == null) {
e.dropComplete(false);
return;
} // 目標ノード
THierarchyTreeNode targetNode = (THierarchyTreeNode) targetPath.getLastPathComponent();
TreePath dropPath = new TreePath(((DefaultTreeModel) this.getModel()).getPathToRoot(targetNode));// 目標パス // 自分の親ノード
THierarchyTreeNode parentNode = (THierarchyTreeNode) list.get(0).getParent();
// ④ 同コンポーネント内のドラッグ&ドロップがないか、 以下の項目をチェックする。
treeTotree = true;
// 親ノードを子ノードにドロップしようとしている場合、処理を終了
TreePath dragPath = new TreePath(((DefaultTreeModel) this.getModel()).getPathToRoot(list.get(0)));// 源パス String strDragPath = dragPath.toString();// 源パス
String strDropPath = dropPath.toString();// 目標パス
String subDragPath = strDragPath.substring(0, strDragPath.length() - 1); if (strDropPath.startsWith(subDragPath)) {
e.dropComplete(false);
return;
}
// 自分に自分をドロップしようとしている場合、処理を終了
if (parentNode.equals(targetNode)) {
e.dropComplete(false);
return;
}
if (targetNode.equals(list.get(0))) {
e.dropComplete(false);
return;
}
e.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); // ⑤ ③.THierarchyTreeNodeに①.転送データを子ノードとして追加する。
if (parentNode != null) {
// tree -> tree
// 転送したノードをTreeから削除
model.removeNodeFromParent(list.get(0));
model.insertNodeInto(list.get(0), targetNode, targetNode.getChildCount());
} else {
// spread -> tree
for (THierarchyTreeNode treeNode : list) {
model.insertNodeInto(treeNode, targetNode, targetNode.getChildCount());
}
} // 刷新Tree控件
((DefaultTreeModel) this.getModel()).reload(list.get(0)); // 展開します
expandAll(dropPath, true); // 選択
this.setSelectionPath(dropPath); // ⑥ ドロップ処理を完了する。
e.dropComplete(true); } else {
e.rejectDrop();
}
} /**
* 拖放完毕后的处理(正确的释放后的处理)
*/
public void dragDropEnd(DragSourceDropEvent e) { // ①ドロップが正常に完了したかをチェックする。
if (!e.getDropSuccess()) {
return;
} // ②転送データ:List<THierarchyTreeNode>を取得する。
List<THierarchyTreeNode> list = TTransferable.getTHerarchyTreeNodeList(e.getDragSourceContext()
.getTransferable()); // ②.転送データが存在しない場合は処理終了
if (list == null || list.isEmpty()) {
return;
} // tree -> spread
if (treeTotree == false) {
// 転送したノードをTreeから削除
DefaultTreeModel model = (DefaultTreeModel) getModel();
model.removeNodeFromParent(list.get(0)); } else {
// tree -> tree
return;
}
// 更新します
((DefaultTreeModel) this.getModel()).reload(); TreePath rootPath = new TreePath(((DefaultTreeModel) this.getModel()).getRoot());
this.setSelectionPath(rootPath); // 展開します
expandAll(rootPath, true);
// 選択
this.setSelectionPath(rootPath); }
以上是树型控件的拖拽, JTextArea中也写类似的拖放代码,即可完成拖拽
注:其中有些类是自定义类(因为要传递一些别的数据),可使用它的父类(如:THierarchyTreeNode->TreeNode)即可
ls比我考虑的要多,应该是考虑到了可以多选拖拽的情形吧,所以才在transfer里面使用List来存储数据。可是
model.removeNodeFromParent(list.get(0));
这句又是为何?只删除第一个元素?这个写死了就把前面的灵活性给抹杀了。
不过要是lz的要求其实简单的多了,特别在targetListener中的drop处理上。因为如果是树,特别是自拖拽的树有许多的限制条件。例如移动后要添加,成功后要从原来的路径上整个删除直至叶子节点的所选分支……
不管怎么说,ls的代码很规范,考虑也比较周全,pf。我的代码分开了五个类,我不愿意都放到一起,看起来很乱。而且由于仓促写的,没有加注释;代码也没有做什么优化和调整。凑合看吧。我就打包发到你邮箱里了。我的代码和楼上的所用到的都是一样的,只是具体处理上有所区别。请结合ls的代码及注释(你能看懂那些日语的大概含义即可)
这句又是为何?只删除第一个元素?这个写死了就把前面的灵活性给抹杀了。 其实上面的代码只是单选拖拽, 在拖拽父节点时,所对应的子节点也要跟着动,因此用List来存储数据,它存储了拖拽的节点和所有子节点
.
只删除第一个元素list(0),是因为只要删除了所选择的节点,那么它的子节点也都删除了