在JTree中拖放节点
我很难创建一个JTree,它允许通过在JTree中拖放节点来重组节点。 这似乎应该相对简单。 我在线查看了一些示例,但我似乎无法在自己的代码中实现它。
例如,sun提供的这允许在不同组件之间拖动到树中,而不是从树本身内拖动。
我还发现这可以让你将文本拖到JTree中,但不能在树中拖动。
import java.awt。*; import java.awt.datatransfer。*; import java.awt.event。*; import java.io. *; import javax.swing。*; import javax.swing.tree。*; public class DndTree {public static void main(String args []){Runnable runner = new Runnable(){public void run(){JFrame f = new JFrame(“DnD JTree”); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel top = new JPanel(new BorderLayout()); JLabel dragLabel = new JLabel(“拖我:”); JTextField text = new JTextField(); text.setDragEnabled(真); top.add(dragLabel,BorderLayout.WEST); top.add(text,BorderLayout.CENTER); f.add(top,BorderLayout.NORTH); final JTree tree = new JTree(); final DefaultTreeModel model =(DefaultTreeModel)tree.getModel(); tree.setTransferHandler(new TransferHandler(){public boolean canImport(TransferHandler.TransferSupport support){if(!support.isDataFlavorSupported(DataFlavor.stringFlavor)||!support.isDrop()){return false;} JTree.DropLocation dropLocation =( JTree.DropLocation)support.getDropLocation(); return dropLocation.getPath()!= null;} public boolean importData(TransferHandler.TransferSupport support){if(!canImport(support)){return false;} JTree.DropLocation dropLocation =( JTree.DropLocation)support.getDropLocation(); TreePath path = dropLocation.getPath(); Transferable transferable = support.getTransferable(); String transferData; try {transferData =(String)transferable.getTransferData(DataFlavor.stringFlavor);} catch( IOException e){return false;} catch(UnsupportedFlavorException e){return false;} int childIndex = dropLocation.getChildIndex(); if(childIndex == -1){childIndex = model.getChildCount(path.getLastPathComponent());} DefaultMutableTreeNode newNode = new 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 pane = new JScrollPane(tree); f.add(pane,BorderLayout.CENTER); JPanel bottom = new JPanel(); JLabel comboLabel = new JLabel(“DropMode”); 字符串选项[] = {“USE_SELECTION”,“ON”,“INSERT”,“ON_OR_INSERT”}; final DropMode mode [] = {DropMode.USE_SELECTION,DropMode.ON,DropMode.INSERT,DropMode.ON_OR_INSERT}; final JComboBox combo = new JComboBox(options); combo.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e){int selectedIndex = combo.getSelectedIndex(); tree.setDropMode(mode [selectedIndex]);}}); bottom.add(comboLabel); bottom.add(组合); f.add(bottom,BorderLayout.SOUTH); f.setSize(300,400); f.setVisible(真); }}; EventQueue.invokeLater(浇道); }}
任何参考或建议都会很棒。 谢谢
之前没有这样做,但快速的谷歌搜索在这里提出了同样的问题: 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-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 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 < 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); } } }