我有一个类结构如下:
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 回答
如果您认为问题是您继承DefaultMutableTreeNode,请尝试使您的DataFlavor成为Object的数组,甚至更好的是ArrayList:
这样您就可以将
copies
列表与您的transferable一起返回 . 也许它会避免这个问题 .这里有一个关于如何使用列表执行此操作的粗略概述: