我刚刚制作了一个简单的应用程序,其中包括 FlowPane 和一些带有按钮的 VBox。
Main类是这样的。
public class Main extends Application {
@Override
public void start(Stage stage) {
Gallery a = new Gallery();
a.setMaxWidth(200);
a.setPrefWidth(200);
Scene scene = new Scene(a);
stage.setTitle("Welcome to JavaFX!");
stage.setScene(scene);
stage.sizeToScene();
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
这个 Gallery.class 是扩展 FlowPane 的主要背景类。
public class Gallery extends FlowPane{
public Gallery() {
super();
PlotterPanel p1 = new PlotterPanel(this, "B1" );
getChildren().add(p1);
PlotterPanel p2 = new PlotterPanel(this, "B2");
getChildren().add(p2);
PlotterPanel p3 = new PlotterPanel(this, "B3" );
getChildren().add(p3);
PlotterPanel p4 = new PlotterPanel(this, "B4" );
getChildren().add(p4);
PlotterPanel p5 = new PlotterPanel(this, "B5" );
getChildren().add(p5);
PlotterPanel p6 = new PlotterPanel(this, "B6" );
getChildren().add(p6);
}
}
PlotterPanel是VBox,有Button,可以在Gallery中拖放。
public class PlotterPanel extends VBox{
private static final String TAB_DRAG_KEY = "titledpane";
private ObjectProperty<VBox> draggingTab;
private Gallery mgallery;
private PlotterPanel self;
public PlotterPanel(Gallery gallery, String name) {
super();
mgallery = gallery;
setPrefWidth(100);
setPrefHeight(100);
self = this;
Button btn = new Button(name);
btn.setEffect(new DropShadow());
getChildren().add(btn);
draggingTab = new SimpleObjectProperty<VBox>();
setOnDragOver(new EventHandler<DragEvent>() {
@Override
public void handle(DragEvent event) {
final Dragboard dragboard = event.getDragboard();
if (dragboard.hasString()
&& TAB_DRAG_KEY.equals(dragboard.getString())
&& draggingTab.get() != null) {
event.acceptTransferModes(TransferMode.MOVE);
event.consume();
}
}
});
setOnDragDropped(new EventHandler<DragEvent>() {
public void handle(final DragEvent event) {
Dragboard db = event.getDragboard();
boolean success = false;
if (db.hasString()) {
Pane parent = mgallery;
Object source = event.getGestureSource();
int sourceIndex = parent.getChildren().indexOf(source);
System.out.println(sourceIndex);
int targetIndex = parent.getChildren().indexOf(self);
System.out.println(targetIndex);
List<Node> nodes = new ArrayList<Node>(parent.getChildren());
if (sourceIndex < targetIndex) {
Collections.rotate(
nodes.subList(sourceIndex, targetIndex + 1), -1);
} else {
Collections.rotate(
nodes.subList(targetIndex, sourceIndex + 1), 1);
}
parent.getChildren().clear();
parent.getChildren().addAll(nodes);
success = true;
}
event.setDropCompleted(success);
event.consume();
}
});
setOnDragDetected(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
Dragboard dragboard = self.startDragAndDrop(TransferMode.MOVE);
ClipboardContent clipboardContent = new ClipboardContent();
clipboardContent.putString(TAB_DRAG_KEY);
dragboard.setContent(clipboardContent);
draggingTab.set(self);
event.consume();
}
});
}
}
问题是,当我在 Gallery 中拖动 PlotterPanel 时,第一次无法拖动它。我在第二次尝试后工作了。 当我开始拖动时,它显示拖动框,但是当我尝试放在另一个节点上时,鼠标点显示 x 符号。 但是当目标已经尝试过要拖动的节点时,我可以将其放在该节点上。
如何使拖放在 JavaFX 中正常工作?
最佳答案
问题在于您接受拖动的条件:
if (dragboard.hasString()
&& TAB_DRAG_KEY.equals(dragboard.getString())
&& draggingTab.get() != null) {
event.acceptTransferModes(TransferMode.MOVE);
event.consume();
}
您正在检查目标的draggingTab
,而不是源。如果目标本身未被拖动,则其 draggingTab
属性仍将为 null。如果您已经拖动了目标,那么它不会为空并且它将接受拖动。
您的意思是使 draggingTab
静态吗?
关于Javafx拖放第一次不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57700207/