问题:我想在JavaFX中的两个不同的TreeTabelViews之间添加一些非对称的拖放。这意味着我想在从A拖动到B时复制,不需要从B到A的任何东西,我想要移动internaly。 到目前为止我的代码可以在下面看到。我知道这只是必须编程的一小部分但我甚至无法使用一个“约束”。
public TreeTableRow<Task> internalMoveFactory(TreeTableView<Task> view) {
TreeTableRow<Task> row = new TreeTableRow<>();
row.setOnDragDetected(event -> {
if (!row.isEmpty()) {
Dragboard db = row.startDragAndDrop(TransferMode.COPY_OR_MOVE);
db.setDragView(row.snapshot(null, null));
ClipboardContent cc = new ClipboardContent();
cc.put(ROW_INDEX, row.getIndex());
MainController.clipboard = row.getTreeItem().getValue(); //I know this is not very nice... but what else should i do?
db.setContent(cc);
event.consume();
}
});
row.setOnDragOver(event -> {
Dragboard db = event.getDragboard();
if (acceptable(db, row)) {
if (isInternal(db,row)) {
event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
event.consume();
}
}
});
row.setOnDragDropped(event -> {
Dragboard db = event.getDragboard();
if (acceptable(db, row)) {
if(isInternal(db,row)) {
int index = (Integer) db.getContent(ROW_INDEX);
TreeItem<Task> item = tree.getTreeItem(index);
Task taskItem = tree.getTreeItem(index).getValue();
item.getParent().getChildren().remove(item);
taskItem.getParentTask().getChildTaskList().remove(taskItem);
getTarget(row).getChildren().add(item);
getTarget(row).getValue().getChildTaskList().add(taskItem);
taskItem.setParentTask(getTarget(row).getValue());
event.setDropCompleted(true);
tree.getSelectionModel().select(item);
event.consume();
}
}
});
return row;
}private boolean isInternal(Dragboard db,TreeTableRow<Task> row) {
TreeTableView source = (TreeTableView) db.getContent(DRAG_SOURCE);
boolean result = source == this.tree;
return result;
}
private boolean acceptable(Dragboard db, TreeTableRow<Task> row) {
boolean result = false;
if (db.hasContent(ROW_INDEX)) {
int index = (Integer) db.getContent(ROW_INDEX);
if (row.getIndex() != index) {
TreeItem<Task> target = getTarget(row);
TreeItem<Task> item = tree.getTreeItem(index);
result = !isParent(item, target);
}
}
return result;
}
// prevent loops in the tree
private boolean isParent(TreeItem parent, TreeItem child) {
boolean result = false;
while (!result && child != null) {
result = child.getParent() == parent;
child = child.getParent();
}
return result;
}
private TreeItem<Task> getTarget(TreeTableRow<Task> row) {
TreeItem<Task> target = tree.getRoot();
if (!row.isEmpty()) {
target = row.getTreeItem();
}
return target;
}
我最大的问题是,我无法序列化行或任务对象 (因为后者有StringProperties)将它们存储在
Dragboard
:
Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: Only serializable objects or ByteBuffer can be used as data with data format [application/test]
at com.sun.javafx.tk.quantum.QuantumClipboard.putContentToPeer(QuantumClipboard.java:642)
at com.sun.javafx.tk.quantum.QuantumClipboard.flush(QuantumClipboard.java:269)
at com.sun.javafx.tk.quantum.QuantumToolkit.startDrag(QuantumToolkit.java:1224)
at javafx.scene.Scene$DnDGesture.dragDetectedProcessed(Scene.java:2953)
at javafx.scene.Scene$DnDGesture.process(Scene.java:3022)
at javafx.scene.Scene$DnDGesture.access$8200(Scene.java:2909)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3773)
问题:有没有办法将对象放到剪贴板而不将它们序列化或存储在全局变量中?我很简单想让Dragboard存储行的源(知道它是否来自不同的TreeTabelView)和我正在拖动的任务。 备注:我知道我可以让任务扩展TreeItem,但这会导致代码中的其他一些奇怪的结构。