Перетащите узел несколько раз с помощью JavaFX - PullRequest
0 голосов
/ 02 июня 2019

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

package application;

import javafx.application.Application;
import javafx.event.Event;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class DragNodeMultipleTimes 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.setOnMousePressed(event -> {
            sourceDisk.setOrgSceneX(event.getSceneX());
            sourceDisk.setOrgSceneY(event.getSceneY());
            sourceDisk.setOrgTranslateX(sourceDisk.getTranslateX());
            sourceDisk.setOrgTranslateY(sourceDisk.getTranslateY());

            sourceDisk.setMouseTransparent(true);

            event.consume();
        });

        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 -> {
            //reset the position of the disk
            sourceDisk.setTranslateX(0);
            sourceDisk.setTranslateY(0);

            sourceDisk.setMouseTransparent(false);
        });

        targetVBox.setOnMouseDragEntered(Event::consume);

        targetVBox.setOnMouseDragOver(event -> System.out.println("VBox: mouseDragOver"));

        targetVBox.setOnMouseDragReleased(event -> {
            ((VBox) (event.getSource())).getChildren().add(0, sourceDisk);

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

            sourceDisk.setMouseTransparent(false);
        });
    }

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

        public double getOrgSceneX() {
            return orgSceneX;
        }

        public void setOrgSceneX(double orgSceneX) {
            this.orgSceneX = orgSceneX;
        }

        public double getOrgSceneY() {
            return orgSceneY;
        }

        public void setOrgSceneY(double orgSceneY) {
            this.orgSceneY = orgSceneY;
        }

        public double getOrgTranslateX() {
            return orgTranslateX;
        }

        public void setOrgTranslateX(double orgTranslateX) {
            this.orgTranslateX = orgTranslateX;
        }

        public double getOrgTranslateY() {
            return orgTranslateY;
        }

        public void setOrgTranslateY(double orgTranslateY) {
            this.orgTranslateY = orgTranslateY;
        }
    }
}

Действия по воспроизведению проблемы:
1) Перетащите левый прямоугольник поверх правого (внутри VBox)
2) Перетащите только что добавленный прямоугольник за пределы VBox
3) Отпустите кнопку мыши

Проблема возникает на шаге 2. Я ожидаю, что VBox больше не получает никаких событийот мыши, так как он покинул свою границу.Этого не происходит, как видно из вывода консоли (onMouseDragOver все еще вызывается).
На шаге 3 выдается исключение, но это происходит потому, что он пытается добавить тот же прямоугольник обратно в VBox.

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

По сути, я пытаюсь выяснить, как получается, что, даже если курсор не находится в границах VBox, он все еще получает события MOUSE_DRAGGED?
Я также открыт дляпредложения других подходов к достижению этого результата.

1 Ответ

0 голосов
/ 03 июня 2019

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

Я думаю, что это так: если ребенок получает событие, все родители также получают его.

Таким образом, вам нужно извлечь диск из VBox, как только он вытащит наружу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...