我正在JTree中实现拖放。 我希望用户能够在树中的不同级别删除节点。
在下面的示例中,假设用户在“孙子A2”和“子C”之间插入一个项目:
root
child A
grandchild A1
grandchild A2
child C
grandchild C1
现在有两种选择:
在SWT中,可以通过在垂直方向上移动节点来实现这一点。水平线指示符将显示树节点插入的嵌套级别。
这在Swing中是否可行?我似乎无法找到相关信息。 Swing中的线指示器始终仅显示在一个级别。
如果没有,是否有解决方法?
答案 0 :(得分:2)
我不相信使用Swing的内置拖放功能可以完全实现您想要的行为。
可能的解决方法是将您的放弃模式设置为ON_OR_INSERT,如下所示:tree.setDropMode(DropMode.ON_OR_INSERT);
ON_OR_INSERT支持直接在节点上或节点之间删除。 INSERT部分支持在“A”和“B”之间删除。然后,您可以允许用户以两种方式之一(或两者)在“A3”之后添加“A”的新孙子:
如果您完全需要您描述的行为,您可能需要为表格编写自定义DropTarget并自己绘制所需的效果(显示放置位置的线条)。我建议尽可能避免这种情况。
答案 1 :(得分:1)
这是bug in the java drop location handling,如果不修改JDK源,很难解决。它仍然没有得到解决,但也有一个related enhancement request可能不切实际的解决方案已被关闭,因为它不会解决。
我能够做到这一点的唯一方法是添加一个虚拟节点作为任何容器节点的最后一个子节点。这很复杂,并且添加了一些可能不合适的行,但允许用户作为容器节点的最后一个子节点删除。
public class TreeDragAndDrop {
private static final int CONTAINER_ROW = 0;
private static final int PLACEHOLDER_ROW = 3;
private JScrollPane getContent() {
JTree tree = new JTree(getTreeModel()) {
// Overridden to prevent placeholder selection via the keyboad
@Override
public void setSelectionInterval(int index0, int index1) {
int index = index0;
// Probably would use a better check for placeholder row in production
// and use a while loop in case the new index is also a placeholder
if (index == PLACEHOLDER_ROW) {
int currentSelection = getSelectionCount() > 0 ? getSelectionRows()[0] : -1;
if (currentSelection < index) {
index++;
} else {
index--;
}
}
super.setSelectionInterval(index, index);
}
// Overridden to prevent placeholder selection via the mouse
@Override
public void setSelectionPath(TreePath path) {
if (path != null && getRowForPath(path) != PLACEHOLDER_ROW) {
super.setSelectionPath(path);
}
}
};
tree.setRootVisible(false);
tree.setDragEnabled(true);
tree.setDropMode(DropMode.INSERT);
tree.setTransferHandler(...);
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.expandRow(CONTAINER_ROW);
return new JScrollPane(tree);
}
protected static TreeModel getTreeModel() {
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
DefaultMutableTreeNode a;
a = new DefaultMutableTreeNode("A");
root.add(a);
a.add(new DefaultMutableTreeNode("X"));
a.add(new DefaultMutableTreeNode("Y"));
a.add(new DefaultMutableTreeNode("")); // Placeholder node
root.add(new DefaultMutableTreeNode("B"));
root.add(new DefaultMutableTreeNode("C"));
return new DefaultTreeModel(root);
}
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.setLocationRelativeTo(null);
f.setVisible(true);
}
// TransferHandler code omitted
}
您可能希望使用自定义渲染器来更改占位符行的外观(例如,隐藏图标,降低高度(尽管不能使其高度为0)等。)