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 静态化吗?