Невозможно поместить прямоугольник в нужное место с помощью JavaFX

Я пытаюсь реализовать полный жест нажатия и перетаскивания с помощью JavaFX. Я хочу перетащить прямоугольник из одного VBox в другой. В событии MOUSE_DRAG_RELEASED, которое происходит в целевом VBox, я пытаюсь добавить перетаскиваемый прямоугольник в качестве дочернего элемента целевого VBox.

Проблема в том, что когда я отпускаю мышь на целевом VBox, прямоугольник не попадает в ожидаемую позицию внутри VBox, а всегда смещается вправо на фиксированное расстояние.

public class DragFromOneVBoxToAnother extends Application {
    private Disk sourceDisk = new Disk();
    private VBox targetVBox = new VBox();

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

    @Override
    public void start(Stage stage) {
        // Build the UI
        GridPane root = getUI();

        // Add the event handlers
        this.addEventHandlers();

        Scene scene = new Scene(root, 800, 600);
        stage.setScene(scene);
        stage.show();
    }

    private GridPane getUI() {
        GridPane pane = new GridPane();
        VBox sourceVBox = new VBox();

        sourceDisk.setWidth(90);
        sourceDisk.setHeight(20);

        sourceVBox.setStyle(" -fx-border-color:red; -fx-border-width: 1; -fx-border-style: solid;");
        targetVBox.setStyle(" -fx-border-color:green; -fx-border-width: 1; -fx-border-style: solid;");

        sourceVBox.getChildren().add(sourceDisk);
        targetVBox.getChildren().add(new Rectangle(200, 20));

        pane.setHgap(200);
        pane.addColumn(0, sourceVBox);
        pane.addColumn(1, targetVBox);
        pane.setPadding(new Insets(200, 100, 200, 100));

        return pane;
    }

    private void addEventHandlers() {
        sourceDisk.setOnMouseEntered(event -> sourceDisk.setCursor(Cursor.HAND));

        sourceDisk.setOnMousePressed(event -> {
            sourceDisk.setOrgSceneX(event.getSceneX());
            sourceDisk.setOrgSceneY(event.getSceneY());
            sourceDisk.setOrgTranslateX(sourceDisk.getTranslateX());
            sourceDisk.setOrgTranslateY(sourceDisk.getTranslateY());

            sourceDisk.setMouseTransparent(true);
            sourceDisk.setCursor(Cursor.CLOSED_HAND);
        });

        sourceDisk.setOnDragDetected(event -> sourceDisk.startFullDrag());

        sourceDisk.setOnMouseDragged(event -> {
            double offsetX = event.getSceneX() - sourceDisk.getOrgSceneX();
            double offsetY = event.getSceneY() - sourceDisk.getOrgSceneY();
            double newTranslateX = sourceDisk.getOrgTranslateX() + offsetX;
            double newTranslateY = sourceDisk.getOrgTranslateY() + offsetY;

            sourceDisk.setTranslateX(newTranslateX);
            sourceDisk.setTranslateY(newTranslateY);
        });

        sourceDisk.setOnMouseReleased(event -> {
            sourceDisk.setMouseTransparent(false);
            sourceDisk.setCursor(Cursor.DEFAULT);
        });

        targetVBox.setOnMouseDragReleased(event -> 
            targetVBox.getChildren().add(sourceDisk));
    }

    private class Disk extends Rectangle {
        private double orgSceneX;
        private double orgSceneY;
        private double orgTranslateX;
        private double orgTranslateY;

        // below, the getters and setters for all the instance variables
        // were removed for brevity
}

Я обнаружил, что, несмотря на то, что визуальное представление перетаскиваемого прямоугольника кажется смещенным при его удалении, дочерний элемент фактически добавляется к целевому VBox (это можно увидеть, потому что граница VBox расширяется после события MOUSE_DRAG_RELEASED) . В чем может быть проблема?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
29
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Во время жеста перетаскивания мышью вы изменяете свойства translateX/translateY узла. Это приводит к тому, что перетаскиваемый узел смещается от положения, в котором новый родитель помещает его в результате этого преобразования. Вам нужно сбросить эти значения, чтобы правильно добавить узел внизу VBox:

targetVBox.setOnMouseDragReleased(event -> {
    targetVBox.getChildren().add(sourceDisk);

    // reset translate values
    sourceDisk.setTranslateX(0);
    sourceDisk.setTranslateY(0);
});

Другие вопросы по теме