有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java使用JavaFX多次拖动节点

我正在尝试将矩形拖动到VBox,然后从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的范围内,它如何仍然接收鼠标拖动的事件
我也愿意接受其他实现这一结果的方法的建议


共 (1) 个答案

  1. # 1 楼答案

    我不太确定,但我有一个假设。 磁盘被添加为VBox的子对象,因此它被视为它的一部分,应用于VBox的相同事件也应用于磁盘。因此,由于磁盘是VBox的一部分,所以现在拖动它的子对象时,鼠标仍在VBox中

    我认为是这样的:如果一个孩子收到一个活动,所有的父母都会收到

    因此,您需要在将磁盘拖出VBox后立即将其从VBox中移除