Javafx 拖放第一次不起作用
Javafx drag-drop does not work in the first time
我刚刚制作了一个简单的应用程序,其中包括 FlowPane 和一些带有按钮的 VBox。
主要class是这样的
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 的主要背景 class。
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 是带有 Button 的 VBox,可以在图库中拖放。
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();
}
});
}
}
问题是当我在图库中拖动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
静态化吗?
我刚刚制作了一个简单的应用程序,其中包括 FlowPane 和一些带有按钮的 VBox。
主要class是这样的
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 的主要背景 class。
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 是带有 Button 的 VBox,可以在图库中拖放。
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();
}
});
}
}
问题是当我在图库中拖动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
静态化吗?