Это ошибка в обработке местоположения отбрасывания java , и ее трудно устранить без изменения источника JDK. Это все еще не решено, но есть также связанный запрос на улучшение с возможными непрактичными обходными путями, который был закрыт, поскольку не будет исправлен.
Единственный способ, которым я смог это сделать, - добавить фиктивный узел в качестве последнего дочернего элемента любого узла контейнера. Это сложно и добавляет строку, которая может быть нежелательной, но позволяет пользователю отбрасываться как последний дочерний элемент узла контейнера.
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 высотой) и т. Д.).