首页 文章

TreeNode DnD问题的子类

提问于
浏览
0

我有一个类结构如下:

DefaultMutableTreeNode
|_
   BCStructure
   |_
   | Module
   |_
   | Section
   |_  
     Page

模块,部分和页面是我在JTree中实际使用的内容 . 如果您运行下面的示例代码,拖放工作 . 请注意,它使用的是DefaultMutableTreeNodes . 但是,如果我将代码放在我使用DefualtMutableTreeNode子类的真实应用程序中,它就不起作用 .

在单步执行代码时,我注意到两个感兴趣的领域 . 首先是:

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());
        }
    }

这是它设置DataFlavor的地方 . 它将它设置为DefualtMutableTreeNode数组,我认为这是正确的,因为DefaultMutableTreeNode是我的节点的超类 . 但这是我认为问题可能存在的一个领域 .

另一点是在调试此代码时,我得到:

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

在拖放失败之前 . 我假设它返回一个不太受欢迎的DataFlavor . 这就是为什么我认为DataFlavor有问题 . 是否有更多我需要做/修改才能使用子类?任何想法或建议?

谢谢!

完整示例代码:

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  0 &&
               target.getLevel()  0 && selRows.length == 1)
            return false;
        // first may have children.
        for(int i = 1; i  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 copies =
                new ArrayList();
            List toRemove =
                new ArrayList();
            DefaultMutableTreeNode node =
                (DefaultMutableTreeNode)paths[0].getLastPathComponent();
            DefaultMutableTreeNode copy = copy(node);
            copies.add(copy);
            toRemove.add(node);
            for(int i = 1; i  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

1 回答

  • 0

    如果您认为问题是您继承DefaultMutableTreeNode,请尝试使您的DataFlavor成为Object的数组,甚至更好的是ArrayList:

    DataFlavor.javaJVMLocalObjectMimeType + ";class=java.util.ArrayList"
    

    这样您就可以将 copies 列表与您的transferable一起返回 . 也许它会避免这个问题 .

    这里有一个关于如何使用列表执行此操作的粗略概述:

    import javax.swing.*;
    import javax.swing.tree.*;
    import java.awt.*;
    import java.awt.datatransfer.DataFlavor;
    import java.awt.datatransfer.Transferable;
    import java.awt.datatransfer.UnsupportedFlavorException;
    import java.io.IOException;
    import java.util.*;
    import java.util.List;
    
    /**
     * Author: Denis Tulskiy
     * Date: 1/5/11
     */
    public class Test extends JFrame {
        class NodeA extends DefaultMutableTreeNode {
    
            NodeA(Object userObject) {
                super(userObject);
            }
        }
        class NodeB extends DefaultMutableTreeNode {
    
            NodeB(Object userObject) {
                super(userObject);
            }
        }
        class NodeC extends DefaultMutableTreeNode {
    
            NodeC(Object userObject) {
                super(userObject);
            }
        }
        private static class MyTransferHandler extends TransferHandler {
            @Override
            public int getSourceActions(JComponent c) {
                return MOVE;
            }
    
            @Override
            protected Transferable createTransferable(JComponent c) {
                JTree tree = (JTree) c;
    
                ArrayList<TreeNode> nodes = new ArrayList<TreeNode>();
                for (TreePath path : tree.getSelectionPaths()) {
                    DefaultMutableTreeNode component = (DefaultMutableTreeNode) path.getLastPathComponent();
                    nodes.add(component);
                }
                return new NodesTransferable(nodes);
            }
    
            @Override
            public boolean canImport(TransferSupport support) {
                return support.isDataFlavorSupported(NodesTransferable.getDataFlavor());
            }
    
            @Override
            public boolean importData(TransferSupport support) {
                if (!canImport(support)) {
                    return false;
                }
                JTree tree = (JTree) support.getComponent();
                List<DefaultMutableTreeNode> data = null;
                try {
                    data = (List<DefaultMutableTreeNode>) support.getTransferable().getTransferData(NodesTransferable.getDataFlavor());
                } catch (UnsupportedFlavorException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
                if (data != null) {
                    Point dropPoint = support.getDropLocation().getDropPoint();
                    TreePath path = tree.getPathForLocation(dropPoint.x, dropPoint.y);
                    DefaultMutableTreeNode parent = (DefaultMutableTreeNode) path.getLastPathComponent();
                    for (DefaultMutableTreeNode node : data) {
                        node.removeFromParent();
                        parent.add(node);
                    }
                    DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
                    model.reload();
                }
                return true;
            }
        }
    
        static class NodesTransferable implements Transferable {
    
            private static DataFlavor dataFlavor;
    
            public static DataFlavor getDataFlavor() {
                if (dataFlavor == null) {
                    try {
                        dataFlavor = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + ";class=java.util.ArrayList");
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                }
                return dataFlavor;
            }
    
            private java.util.List<TreeNode> nodes;
    
            NodesTransferable(List<TreeNode> nodes) {
                this.nodes = nodes;
            }
    
            @Override
            public DataFlavor[] getTransferDataFlavors() {
    
                return new DataFlavor[]{getDataFlavor()};
            }
    
            @Override
            public boolean isDataFlavorSupported(DataFlavor flavor) {
                return flavor.match(dataFlavor);
            }
    
            @Override
            public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
                return nodes;
            }
        }
    
        public Test() {
            JTree tree = new JTree();
            tree.setDragEnabled(true);
            tree.setDropMode(DropMode.ON_OR_INSERT);
            DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
            NodeA child = new NodeA("nodea");
            root.add(child);
            child.add(new NodeB("nodeb"));
            child.add(new NodeC("nodec"));
    
            tree.setModel(new DefaultTreeModel(root));
    
            tree.setTransferHandler(new MyTransferHandler());
            setLayout(new BorderLayout());
            add(tree, BorderLayout.CENTER);
            setSize(300, 400);
            setLocationRelativeTo(null);
            setDefaultCloseOperation(EXIT_ON_CLOSE);
        }
    
        public static void main(String[] args) {
            new Test().setVisible(true);
        }
    }
    

相关问题