【问题标题】:Get mouse position on node relative to it's coordinates and transforms获取节点上相对于其坐标和变换的鼠标位置
【发布时间】:2013-08-11 20:15:42
【问题描述】:

我有 3D 场景,我在场景中有窗格,它有一个 x 轴旋转变换,我想将此窗格用作战略游戏板,但我有问题。

当我在窗格中输入鼠标时,它给了我错误的光标位置。

例如,当我从左上角(红色圆圈)在窗格内(带有黑色边框的旋转窗格)输入鼠标时,它应该显示我 (0,0) 作为窗格内的光标位置,但它显示类似于 (200 , 400)。

我该如何解决这个问题?

或者换句话说,如何获取节点上相对于节点及其变换的鼠标坐标?

这是一个例子:

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.scene.transform.RotateBuilder;
import javafx.stage.Stage;


public class JFXRotationXOrds  extends Application{

    @Override
    public void start(Stage primaryStage) throws Exception {
        VBox root = new VBox();
        root.getChildren().add(new Rectangle(20, 20, Color.BLUE));  
        root.getChildren().add(new Circle(20, Color.RED));
        //root.rotateProperty().set(30);
        root.getTransforms().add(RotateBuilder.create().angle(-30).pivotX(0).pivotY(100).axis(new Point3D(1, 0, 0)).build());
        root.setStyle("-fx-border-color: black; -fx-border-width:5; ");

        root.setOnMouseMoved(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent arg0) {
                if(arg0.getEventType() == MouseEvent.MOUSE_MOVED){
                    System.out.println(arg0.getX() + "," + arg0.getY());
                }

            }
        });

        Scene scene = new Scene(root, 200, 500);
        primaryStage.setTitle("Rotation Coordinates Example");
        primaryStage.setScene(scene);
        scene.setCamera(PerspectiveCameraBuilder.create().fieldOfView(10).build());
        primaryStage.show();

    }

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

【问题讨论】:

    标签: java javafx javafx-2


    【解决方案1】:

    更新

    问题已在JDK8 Early Access Release 中修复。你可以下载那个版本,或者等它出来。作为这张票的一部分,它已在 2 月修复:RT-28129

    已编辑

    我输入了ticket on the JavaFX Jira。您可以关注它以查看状态更新。

    我已更新演示以反映您的问题。当转换使用 z 轴时它似乎有效(昨天 - 今天对我不同),但当转换在 X 或 Y 轴上时不起作用。

    希望这对你有所帮助。

    import javafx.application.Application;
    import javafx.event.EventHandler;
    import javafx.geometry.Point3D;
    import javafx.scene.PerspectiveCamera;
    import javafx.scene.Scene;
    import javafx.scene.input.MouseEvent;
    import javafx.scene.layout.VBox;
    import javafx.scene.transform.Rotate;
    import javafx.scene.transform.RotateBuilder;
    import javafx.stage.Stage;
    
    
    public class JFXRotationXOrds  extends Application{
    
        @Override
        public void start(Stage primaryStage) throws Exception {
            VBox root = new VBox();
            final Rotate rotate = RotateBuilder.create().angle(80).pivotX(100).pivotY(100).pivotZ(0).axis(new Point3D(1,0,0)).build();
            root.getTransforms().add(rotate);
            root.setStyle("-fx-border-color: black; -fx-border-width:5; ");
    
            root.setOnMouseMoved(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent arg0) {
                    if(arg0.getEventType() == MouseEvent.MOUSE_MOVED){
                        System.out.println(arg0.getSceneX() + "," + arg0.getSceneY());
                    }
                }
            });
    
            Scene scene = new Scene(root, 200, 500);
            PerspectiveCamera camera = new PerspectiveCamera();
            scene.setCamera(camera);
            primaryStage.setTitle("BorderPane Example");
            primaryStage.setScene(scene);
            primaryStage.show();
    
        }
    
        public static void main(String[] args){
            Application.launch(args);
        }
    }
    

    【讨论】:

    • 在 2D 中它可以正常工作,但在 3D 中却不行,尝试将 3D 旋转添加到您的根并为您的场景设置透视相机。
    • 啊 - 您确实在 X 轴上旋转,但您的屏幕截图似乎表明围绕 Z 轴旋转。我现在可以看到问题了...我想您也许可以使用此处的公式进行一些计算(但尚未进行数学证明):docs.oracle.com/javafx/2/api/javafx/scene/transform/Affine.html
    • @Eeliya - 这个问题似乎在 JDK8 早期访问版本中得到了解决。有关详细信息,请参阅答案的更新。
    【解决方案2】:

    由于您没有发布任何代码,这听起来很明显,但是您是否将鼠标事件处理程序添加到窗格中?如果是这样(在我尝试重新创建您的问题时), event.getX() 和 event.getY() 方法返回了预期的位置。

    (您使用 getSceneX() 和 getSceneY() 吗?在这种情况下更改为 getX() 和 getY())

    另一种方法是通过窗格的位置来校正您获得的鼠标位置(场景中的位置)。

    您可以对 x、y、z 轴执行此操作:

    while (node != null){
       shift += node.getLayoutY(); 
       node = node.getParent();
    }
    

    然后将这个移位减去你得到的指针的位置

    编辑:查看您的代码后,您似乎正在将 MouseEvent 处理程序添加到根对象。因此,当鼠标在根对象上时触发该事件。例如,如果将其添加到矩形中,鼠标的位置将相对于矩形。

    以下代码对我有用(但可能无法很好地重现您的问题)。

    公共类 JFXRotationXOrds 扩展应用程序{

    @Override
    public void start(Stage primaryStage) throws Exception {
        VBox root = new VBox();
    
        Rectangle rect = new Rectangle(20, 20, Color.BLUE);
        rect.setOnMouseMoved(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent arg0) {
                if(arg0.getEventType() == MouseEvent.MOUSE_MOVED){
                    System.out.println("Rect : " + arg0.getX() + "," + arg0.getY());
                }
    
            }
        });
        root.getChildren().add(rect);  
        root.getChildren().add(new Circle(20, Color.RED));
        //root.rotateProperty().set(30);
        root.getTransforms().add(RotateBuilder.create().angle(30).pivotX(0).pivotY(100).pivotZ(100).build());
        root.setStyle("-fx-border-color: black; -fx-border-width:5; ");
    
        root.setOnMouseMoved(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent arg0) {
                if(arg0.getEventType() == MouseEvent.MOUSE_MOVED){
                    System.out.println(arg0.getX() + "," + arg0.getY());
                }
    
            }
        });
    
        Scene scene = new Scene(root, 200, 500);
        primaryStage.setTitle("Rotation Coordinates Example");
        primaryStage.setScene(scene);
        primaryStage.show();
    
    }
    
    public static void main(String[] args){
        Application.launch(args);
    }
    }
    

    【讨论】:

    • 我测试了您的编辑,结果没有变化。仍然根据未转换的节点报告 x/y 坐标。 ://
    • 所以你将 mouseMouved 事件添加到矩形,然后将此矩形添加到根节点?我会更深入地研究它。
    • @NickRippe 编辑后的代码似乎对我有用...在您的演示中,您将事件添加到根节点。
    • 您没有设置旋转轴。仅当旋转轴不是 Z 轴(默认为 Z 轴)时才会出现问题。您编辑的示例未设置轴,因此它在 Z 轴上旋转。尝试将此添加到您的构建器:.axis(new Point3D(1, 0, 0))
    • 我确实设置了轴。我需要在具有 3D 变换的节点上获取鼠标坐标。在 2D 中我可以做到。但我需要 3D。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-08
    相关资源
    最近更新 更多