我最近在学习JTree的用法,需要使用JTree的节点,初步想法是拖动其节点至JTextArea中显示,只需要显示节点名字即可,希望高手们能指点一下,我的mail: [email protected],

解决方案 »

  1.   

    JTree的节点可以这样拖动的吗?按你的需求应该是把节点的名字复制到JTextArea里面吧。
      当你选中节点的时候,你是知道如何去获取节点的名字的。你可以使用快捷菜单去复制,把拿到的值放到一个变量里面去存储。当在JTextArea里面的时候,在通过那个中间变量拿出来设置进去就OK。
      不知是否是你所想要的?
      

  2.   

    拖拽倒是没有什么问题。只是比较麻烦。你可以参考一下api文档中关于dnd的介绍。
    有点忙,如果你需要我可以写个简单的例子出来。但是需要些时间。
      

  3.   

    这几天正好做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)即可
      

  4.   

    哦~~楼上捷足先登了。
    ls比我考虑的要多,应该是考虑到了可以多选拖拽的情形吧,所以才在transfer里面使用List来存储数据。可是
    model.removeNodeFromParent(list.get(0));
    这句又是为何?只删除第一个元素?这个写死了就把前面的灵活性给抹杀了。
    不过要是lz的要求其实简单的多了,特别在targetListener中的drop处理上。因为如果是树,特别是自拖拽的树有许多的限制条件。例如移动后要添加,成功后要从原来的路径上整个删除直至叶子节点的所选分支……
    不管怎么说,ls的代码很规范,考虑也比较周全,pf。我的代码分开了五个类,我不愿意都放到一起,看起来很乱。而且由于仓促写的,没有加注释;代码也没有做什么优化和调整。凑合看吧。我就打包发到你邮箱里了。我的代码和楼上的所用到的都是一样的,只是具体处理上有所区别。请结合ls的代码及注释(你能看懂那些日语的大概含义即可)
      

  5.   

    model.removeNodeFromParent(list.get(0)); 
    这句又是为何?只删除第一个元素?这个写死了就把前面的灵活性给抹杀了。 其实上面的代码只是单选拖拽, 在拖拽父节点时,所对应的子节点也要跟着动,因此用List来存储数据,它存储了拖拽的节点和所有子节点
    .
    只删除第一个元素list(0),是因为只要删除了所选择的节点,那么它的子节点也都删除了