子场景 Javafx 中的鼠标偏移

Mouse offsets in a Subscene Javafx

有没有办法让子场景中的鼠标事件 getSceneX() 和 getSceneY() 从零开始?

我的理解(可能不正确)如果您在 SubScene 上设置鼠标事件侦听器,则报告的 x,y 坐标将仅基于该 SubScene(例如 SubScene 顶部的 y=0,x= 0 在 SubScene 的左边)。

此示例应用程序中似乎发生的情况是,报告的 x、y 坐标基于连续场景,而不是听者所附加的子场景。

对于此示例,在 SubScene 的顶部,y 报告为 46 而不是 0。

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.SubScene;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Background;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class SubsceneExample extends Application {

    private final double sceneWidth = 600;
    private final double sceneHeight = 600;

    private double mousePosX;
    private double mousePosY;

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

        VBox root = new VBox();

        VBox controls = createControls();
        root.getChildren().add(controls);

        Pane scenePane = createPane();
        SubScene subScene = new SubScene(scenePane, sceneWidth, sceneHeight);
        subScene.setFill(Color.BLACK);
        handleMouseEvents(subScene);
        root.getChildren().add(subScene);

        Scene scene = new Scene(root, sceneWidth, sceneHeight);
        stage.setScene(scene);
        stage.setTitle("Subscene Example");
        stage.show();
    }

    private Pane createPane() {
        Pane pane = new Pane();
        pane.setPrefSize(sceneWidth, sceneHeight);
        pane.setMaxSize(Pane.USE_COMPUTED_SIZE, Pane.USE_COMPUTED_SIZE);
        pane.setMinSize(Pane.USE_COMPUTED_SIZE, Pane.USE_COMPUTED_SIZE);
        pane.setBackground(Background.EMPTY);
        return pane;
    }

    private VBox createControls() {
        HBox hBox = new HBox(new Button("Button A"));
        hBox.setAlignment(Pos.CENTER);
        VBox controls = new VBox(10, hBox);
        controls.setPadding(new Insets(10));
        return controls;
    }

    private void handleMouseEvents(SubScene subScene) {
        subScene.setOnMousePressed((MouseEvent me) -> {
                    mousePosX = me.getSceneX();
                    mousePosY = me.getSceneY();
                    System.out.printf("press:: x=%.2f, y=%.2f%n", mousePosX, mousePosY);
                }
        );

        subScene.setOnMouseDragged((MouseEvent me) -> {
                    mousePosX = me.getSceneX();
                    mousePosY = me.getSceneY();
                    System.out.printf("drag:: x=%.2f, y=%.2f%n", mousePosX, mousePosY);
                }
        );
    }

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

}

好的,所以我澄清了鼠标事件总是相对于包含场景的。

因此,对于我的示例,我希望针对子场景组件返回的 x、y 和拖动事件为 zero-ed。

我试验发现,最简单的方法是获取子场景的边界“Bounds ofParent = subScene.getBoundsInParent();”并用它来偏移鼠标位置

答案如下:

import javafx.application.Application;
import javafx.geometry.Bounds;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.SubScene;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Background;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class SubsceneExample extends Application {

    private final double sceneWidth = 600;
    private final double sceneHeight = 600;

    private double mousePosX;
    private double mousePosY;

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

        VBox root = new VBox();

        VBox controls = createControls();
        root.getChildren().add(controls);

        Pane scenePane = createPane();
        SubScene subScene = new SubScene(scenePane, sceneWidth, sceneHeight);
        subScene.setFill(Color.BLACK);
        handleMouseEvents(subScene);
        root.getChildren().add(subScene);

        Scene scene = new Scene(root, sceneWidth, sceneHeight);
        stage.setScene(scene);
        stage.setTitle("Subscene Example");
        stage.show();
    }

    private Pane createPane() {
        Pane pane = new Pane();
        pane.setPrefSize(sceneWidth, sceneHeight);
        pane.setMaxSize(Pane.USE_COMPUTED_SIZE, Pane.USE_COMPUTED_SIZE);
        pane.setMinSize(Pane.USE_COMPUTED_SIZE, Pane.USE_COMPUTED_SIZE);
        pane.setBackground(Background.EMPTY);
        return pane;
    }

    private VBox createControls() {
        HBox hBox = new HBox(new Button("Button A"));
        hBox.setAlignment(Pos.CENTER);
        VBox controls = new VBox(10, hBox);
        controls.setPadding(new Insets(10));
        return controls;
    }

    private void handleMouseEvents(SubScene subScene) {
        subScene.setOnMousePressed((MouseEvent me) -> {
                    mousePosX = me.getSceneX();
                    mousePosY = me.getSceneY();
                    Bounds ofParent = subScene.getBoundsInParent();
                    if (mousePosY >= ofParent.getMinY()) {
                        System.out.printf("press:: x=%.2f, y=%.2f%n", mousePosX - ofParent.getMinX(), mousePosY - ofParent.getMinY());
                    }
                }
        );

        subScene.setOnMouseDragged((MouseEvent me) -> {
                    mousePosX = me.getSceneX();
                    mousePosY = me.getSceneY();
                    Bounds ofParent = subScene.getBoundsInParent();
                    if (mousePosY >= ofParent.getMinY()) {
                        System.out.printf("drag:: x=%.2f, y=%.2f%n", mousePosX - ofParent.getMinX(), mousePosY - ofParent.getMinY());
                    }
                }
        );
    }

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

}