当前位置: 首页 > 面试题库 >

在JTree中拖放节点

梁丘兴腾
2023-03-14
问题内容

我在创建JTree时遇到困难,该JTree允许通过将节点拖放到JTree中进行重组。看来应该比较简单。我在网上看过示例,但似乎无法在自己的代码中实现它。

例如,sun提供的这种功能允许在不同组件之间拖动到树中,但不能从树本身内部拖动。

而且我也发现了这一点,它允许您将文本拖到JTree中,但不能拖到树中。

导入java.awt。*;
导入java.awt.datatransfer。*;
导入java.awt.event。*;
导入java.io. *;
导入javax.swing。*;
导入javax.swing.tree。*;

公共类DndTree {

    公共静态void main(String args []){
        可运行的亚军=新的可运行(){

            公共无效run(){
                JFrame f = new JFrame(“ DnD JTree”);
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                JPanel顶部= new JPanel(new BorderLayout());
                JLabel dragLabel =新的JLabel(“ Drag me:”);
                JTextField文本=新的JTextField();
                text.setDragEnabled(true);
                top.add(dragLabel,BorderLayout.WEST);
                top.add(text,BorderLayout.CENTER);
                f.add(top,BorderLayout.NORTH);

                最终的JTree树= new JTree();
                最终的DefaultTreeModel模型=(DefaultTreeModel)tree.getModel();
                tree.setTransferHandler(new TransferHandler(){

                    public boolean canImport(TransferHandler.TransferSupport support){
                        如果(!support.isDataFlavorSupported(DataFlavor.stringFlavor)
                                || !support.isDrop()){
                            返回false;
                        }

                        JTree.DropLocation dropLocation =
                                (JTree.DropLocation)support.getDropLocation();

                        return dropLocation.getPath()!= null;
                    }

                    public boolean importData(TransferHandler.TransferSupport支持){
                        如果(!canImport(support)){
                            返回false;
                        }

                        JTree.DropLocation dropLocation =
                                (JTree.DropLocation)support.getDropLocation();

                        TreePath路径= dropLocation.getPath();

                        可转让可转让= support.getTransferable();

                        字符串transferData;
                        尝试{
                            transferData =(String)transferable.getTransferData(
                                    DataFlavor.stringFlavor);
                        } catch(IOException e){
                            返回false;
                        } catch(UnsupportedFlavorException e){
                            返回false;
                        }

                        int childIndex = dropLocation.getChildIndex();
                        如果(childIndex == -1){
                            childIndex = model.getChildCount(path.getLastPathComponent());
                        }

                        DefaultMutableTreeNode newNode =
                                新的DefaultMutableTreeNode(transferData);
                        DefaultMutableTreeNode parentNode =
                                (DefaultMutableTreeNode)path.getLastPathComponent();
                        model.insertNodeInto(newNode,parentNode,childIndex);

                        TreePath newPath = path.pathByAddingChild(newNode);
                        tree.makeVisible(newPath);
                        tree.scrollRectToVisible(tree.getPathBounds(newPath));

                        返回true;
                    }
                });

                JScrollPane窗格=新的JScrollPane(tree);
                f.add(窗格,BorderLayout.CENTER);

                JPanel bottom =新的JPanel();
                JLabel comboLabel =新的JLabel(“ DropMode”);
                字符串选项[] = {“ USE_SELECTION”,
                    “ ON”,“ INSERT”,“ ON_OR_INSERT”
                };
                最终的DropMode模式[] = {DropMode.USE_SELECTION,
                    DropMode.ON,DropMode.INSERT,DropMode.ON_OR_INSERT};
                最终的JComboBox组合=新的JComboBox(选项);
                combo.addActionListener(new ActionListener(){

                    公共无效actionPerformed(ActionEvent e){
                        int selectedIndex = combo.getSelectedIndex();
                        tree.setDropMode(mode [selectedIndex]);
                    }
                });
                bottom.add(comboLabel);
                bottom.add(combo);
                f.add(底部,BorderLayout.SOUTH);
                f.setSize(300,400);
                f.setVisible(true);
            }
        };
        EventQueue.invokeLater(runner);
    }
}

任何参考或建议将是巨大的。谢谢


问题答案:

之前没有做过,但是谷歌快速搜索在这里出现了同样的问题:http : //www.coderanch.com/t/346509/GUI/java/JTree-drag-
drop-inside-one
它可以正常工作您可以查看的实现。

这是Craig Wood发布的相关代码:

import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.util.*;
import java.util.List;
import javax.swing.*;
import javax.swing.tree.*;

public class TreeDragAndDrop {
    private JScrollPane getContent() {
        JTree tree = new JTree();
        tree.setDragEnabled(true);
        tree.setDropMode(DropMode.ON_OR_INSERT);
        tree.setTransferHandler(new TreeTransferHandler());
        tree.getSelectionModel().setSelectionMode(
                TreeSelectionModel.CONTIGUOUS_TREE_SELECTION);
        expandTree(tree);
        return new JScrollPane(tree);
    }

    private void expandTree(JTree tree) {
        DefaultMutableTreeNode root =
            (DefaultMutableTreeNode)tree.getModel().getRoot();
        Enumeration e = root.breadthFirstEnumeration();
        while(e.hasMoreElements()) {
            DefaultMutableTreeNode node =
                (DefaultMutableTreeNode)e.nextElement();
            if(node.isLeaf()) continue;
            int row = tree.getRowForPath(new TreePath(node.getPath()));
            tree.expandRow(row);
        }
    }

    public static void main(String[] args) {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(new TreeDragAndDrop().getContent());
        f.setSize(400,400);
        f.setLocation(200,200);
        f.setVisible(true);
    }
}

class TreeTransferHandler extends TransferHandler {
    DataFlavor nodesFlavor;
    DataFlavor[] flavors = new DataFlavor[1];
    DefaultMutableTreeNode[] nodesToRemove;

    public TreeTransferHandler() {
        try {
            String mimeType = DataFlavor.javaJVMLocalObjectMimeType +
                              ";class=\"" +
                javax.swing.tree.DefaultMutableTreeNode[].class.getName() +
                              "\"";
            nodesFlavor = new DataFlavor(mimeType);
            flavors[0] = nodesFlavor;
        } catch(ClassNotFoundException e) {
            System.out.println("ClassNotFound: " + e.getMessage());
        }
    }

    public boolean canImport(TransferHandler.TransferSupport support) {
        if(!support.isDrop()) {
            return false;
        }
        support.setShowDropLocation(true);
        if(!support.isDataFlavorSupported(nodesFlavor)) {
            return false;
        }
        // Do not allow a drop on the drag source selections.
        JTree.DropLocation dl =
                (JTree.DropLocation)support.getDropLocation();
        JTree tree = (JTree)support.getComponent();
        int dropRow = tree.getRowForPath(dl.getPath());
        int[] selRows = tree.getSelectionRows();
        for(int i = 0; i < selRows.length; i++) {
            if(selRows[i] == dropRow) {
                return false;
            }
        }
        // Do not allow MOVE-action drops if a non-leaf node is
        // selected unless all of its children are also selected.
        int action = support.getDropAction();
        if(action == MOVE) {
            return haveCompleteNode(tree);
        }
        // Do not allow a non-html" target="_blank">leaf node to be copied to a level
        // which is less than its source level.
        TreePath dest = dl.getPath();
        DefaultMutableTreeNode target =
            (DefaultMutableTreeNode)dest.getLastPathComponent();
        TreePath path = tree.getPathForRow(selRows[0]);
        DefaultMutableTreeNode firstNode =
            (DefaultMutableTreeNode)path.getLastPathComponent();
        if(firstNode.getChildCount() > 0 &&
               target.getLevel() < firstNode.getLevel()) {
            return false;
        }
        return true;
    }

    private boolean haveCompleteNode(JTree tree) {
        int[] selRows = tree.getSelectionRows();
        TreePath path = tree.getPathForRow(selRows[0]);
        DefaultMutableTreeNode first =
            (DefaultMutableTreeNode)path.getLastPathComponent();
        int childCount = first.getChildCount();
        // first has children and no children are selected.
        if(childCount > 0 && selRows.length == 1)
            return false;
        // first may have children.
        for(int i = 1; i < selRows.length; i++) {
            path = tree.getPathForRow(selRows[i]);
            DefaultMutableTreeNode next =
                (DefaultMutableTreeNode)path.getLastPathComponent();
            if(first.isNodeChild(next)) {
                // Found a child of first.
                if(childCount > selRows.length-1) {
                    // Not all children of first are selected.
                    return false;
                }
            }
        }
        return true;
    }

    protected Transferable createTransferable(JComponent c) {
        JTree tree = (JTree)c;
        TreePath[] paths = tree.getSelectionPaths();
        if(paths != null) {
            // Make up a node array of copies for transfer and
            // another for/of the nodes that will be removed in
            // exportDone after a successful drop.
            List<DefaultMutableTreeNode> copies =
                new ArrayList<DefaultMutableTreeNode>();
            List<DefaultMutableTreeNode> toRemove =
                new ArrayList<DefaultMutableTreeNode>();
            DefaultMutableTreeNode node =
                (DefaultMutableTreeNode)paths[0].getLastPathComponent();
            DefaultMutableTreeNode copy = copy(node);
            copies.add(copy);
            toRemove.add(node);
            for(int i = 1; i < paths.length; i++) {
                DefaultMutableTreeNode next =
                    (DefaultMutableTreeNode)paths[i].getLastPathComponent();
                // Do not allow higher level nodes to be added to list.
                if(next.getLevel() < node.getLevel()) {
                    break;
                } else if(next.getLevel() > node.getLevel()) {  // child node
                    copy.add(copy(next));
                    // node already contains child
                } else {                                        // sibling
                    copies.add(copy(next));
                    toRemove.add(next);
                }
            }
            DefaultMutableTreeNode[] nodes =
                copies.toArray(new DefaultMutableTreeNode[copies.size()]);
            nodesToRemove =
                toRemove.toArray(new DefaultMutableTreeNode[toRemove.size()]);
            return new NodesTransferable(nodes);
        }
        return null;
    }

    /** Defensive copy used in createTransferable. */
    private DefaultMutableTreeNode copy(TreeNode node) {
        return new DefaultMutableTreeNode(node);
    }

    protected void exportDone(JComponent source, Transferable data, int action) {
        if((action & MOVE) == MOVE) {
            JTree tree = (JTree)source;
            DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
            // Remove nodes saved in nodesToRemove in createTransferable.
            for(int i = 0; i < nodesToRemove.length; i++) {
                model.removeNodeFromParent(nodesToRemove[i]);
            }
        }
    }

    public int getSourceActions(JComponent c) {
        return COPY_OR_MOVE;
    }

    public boolean importData(TransferHandler.TransferSupport support) {
        if(!canImport(support)) {
            return false;
        }
        // Extract transfer data.
        DefaultMutableTreeNode[] nodes = null;
        try {
            Transferable t = support.getTransferable();
            nodes = (DefaultMutableTreeNode[])t.getTransferData(nodesFlavor);
        } catch(UnsupportedFlavorException ufe) {
            System.out.println("UnsupportedFlavor: " + ufe.getMessage());
        } catch(java.io.IOException ioe) {
            System.out.println("I/O error: " + ioe.getMessage());
        }
        // Get drop location info.
        JTree.DropLocation dl =
                (JTree.DropLocation)support.getDropLocation();
        int childIndex = dl.getChildIndex();
        TreePath dest = dl.getPath();
        DefaultMutableTreeNode parent =
            (DefaultMutableTreeNode)dest.getLastPathComponent();
        JTree tree = (JTree)support.getComponent();
        DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
        // Configure for drop mode.
        int index = childIndex;    // DropMode.INSERT
        if(childIndex == -1) {     // DropMode.ON
            index = parent.getChildCount();
        }
        // Add data to model.
        for(int i = 0; i < nodes.length; i++) {
            model.insertNodeInto(nodes[i], parent, index++);
        }
        return true;
    }

    public String toString() {
        return getClass().getName();
    }

    public class NodesTransferable implements Transferable {
        DefaultMutableTreeNode[] nodes;

        public NodesTransferable(DefaultMutableTreeNode[] nodes) {
            this.nodes = nodes;
         }

        public Object getTransferData(DataFlavor flavor)
                                 throws UnsupportedFlavorException {
            if(!isDataFlavorSupported(flavor))
                throw new UnsupportedFlavorException(flavor);
            return nodes;
        }

        public DataFlavor[] getTransferDataFlavors() {
            return flavors;
        }

        public boolean isDataFlavorSupported(DataFlavor flavor) {
            return nodesFlavor.equals(flavor);
        }
    }
}


 类似资料:
  • 我想知道如何实现这个功能: 我有一个可编辑的JTree,可以编辑节点的名称。如果我有一个节点是分支节点(其中有一些叶节点),并且该分支节点在编辑时展开,编辑后,该节点将折叠。 编辑完成后,如果分支节点打开,我想让它保持打开状态,如果分支节点折叠,我想让它折叠。 我试图查看TreeWireExpandListener,但它似乎无法解决我的问题,因为在调用这些方法之前,我需要识别实际节点是否处于编辑模

  • 所以,我有一个contenteditable div--我正在制作一个所见即所得编辑器:粗体、斜体、格式化,什么都行,最近的是:插入花哨的图像(在花哨的框中,加上标题)。 用户通过一个对话框添加这些精美的图像:他们填写细节,上传图像,然后和其他编辑器函数一样,我使用按用户的选择将其插入。 所以,现在我的用户可以在一个漂亮的图像中扑通一声--他们需要能够移动它。用户需要能够单击和拖动图像(花式框和所

  • 我在Windows JVM 7_25中测试了此代码,它运行良好。 当我用JVM在Linux测试相同的代码时7_25我得到了这个错误堆栈: (以及更多) < code > int incoming index = integer . parse int(drag board . getstring())的内容;为空 你能告诉我如何解决这个问题或重写代码吗?

  • 问题内容: 如何设置JTable以便能够将行拖到表中的其他索引。例如,如果我有5行,并且想将第4行拖到第2个位置? 问题答案: 查看Java教程的拖放部分。有关如何实现此功能的示例有一些。

  • 问题内容: 我最近开始使用Swift来构建OS X应用程序,我想知道如何实现拖放区域。 更具体地说,我构建了一个处理图像的应用程序,但目前,用户必须手动输入输入图像的路径或使用文件选择器(这很烦人)。我想改进我的应用程序,允许用户通过简单的拖放输入图像(我只需要检索表示图像路径的String即可)。 我怎样才能做到这一点? 问题答案: 这是我在应用程序中使用的示例。 如有必要,将一致性添加到子类声

  • 我试图将JTree节点可视化为JButton,我已经尝试使用JButton对象创建一个默认可变树节点,并将其添加到JTree中: 这些只显示带有黑色参数的错误行。 搜索网络我只发现我需要一个类,但没有一个结果显示如何使用它。 是否有一些教程可以让我找到一些示例来完成任务?