JavaFX通过拖放

时间:2017-03-14 09:24:56

标签: javafx drag-and-drop scrollpane

我在ScrollPane中有一个非常大的StackPane(3000x2000)。我们的想法是将它用作一个大型的绘图板,用户可以在其中创建节点并拖动它们,以创建Mindmaps等。问题是拖放:如果scrollPane位于"起始位置",它的工作正常,因此Hvalue和Vvalue都是0.但是一旦你滚动了一下,DragEvent.getX()的值和.getY()返回是相对于窗格的可见部分,而不是它的整个大小。这意味着您无法正确拖放。我创建了一个测试类来说明问题而没有任何过时的代码:

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DataFormat;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

public class DragTestClass extends Application{

    public static void problem(Circle circle, ScrollPane scrollPane, StackPane pane, DataFormat dataFormat){
        circle.setOnDragDetected(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent event) {
                    Dragboard db = circle.startDragAndDrop(TransferMode.ANY);
                    ClipboardContent content = new ClipboardContent();
                    content.put(dataFormat,0); // normally, ID of node
                    db.setContent(content);
                    event.consume();
                }
            });

        scrollPane.setOnDragDropped(new EventHandler<DragEvent>() {
                @Override
                public void handle(DragEvent event) {
                    Dragboard db = event.getDragboard();
                    if(db.hasContent(dataFormat) && db.getContent(dataFormat) instanceof Integer){
                        int index = (Integer) db.getContent(dataFormat);
                        Circle node = (Circle) pane.getChildren().get(index);
                        node.setManaged(false);
                        // this is the problematic part
                        node.setTranslateX(event.getX() - node.getCenterX());
                        node.setTranslateY(event.getY() - node.getCenterY());

                        event.setDropCompleted(true);
                        event.consume();
                    }
                }
        });

        scrollPane.setOnDragOver(new EventHandler<DragEvent>() {
            public void handle(DragEvent event) {
                event.acceptTransferModes(TransferMode.ANY);
                event.consume();
            }
        });
    }

    @Override
    public void start(Stage primaryStage) throws Exception {

        ScrollPane scrollPane = new ScrollPane();
        StackPane pane = new StackPane();
        DataFormat dataFormat = new DataFormat("DragDropFormat");
        int width = 1000;
        int height = 1000;
        pane.setMinHeight(height);
        pane.setMaxHeight(height);
        pane.setMinWidth(width);
        pane.setMaxWidth(width);
        Circle circle = new Circle(50,50,20); // normally a StackPane
        circle.setManaged(false);
        pane.getChildren().add(circle);
        pane.setAlignment(Pos.TOP_LEFT);
        scrollPane.setContent(pane);

        problem(circle, scrollPane, pane, dataFormat);

        Scene scene = new Scene(scrollPane, 400, 400);
        primaryStage.setTitle("Problem");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

}

我的想法是在节点的转换中添加一些内容,例如scrollPane.getHvalue()* width,但这似乎并不起作用。也许我只是搜索了错误的关键字,但我还没有发现任何有用的信息,所以如果问题在其他地方得到解答,我很抱歉。在此先感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

我明白了!在StackPane上设置EventHandler(ScrollPane的内容,而不是ScrollPane本身)就可以了。显然,event.getX()返回的坐标是相对于具有EventHandler的节点。在这个例子中:

pane.setOnDragDropped...