获取相对于其坐标和变换的节点上的鼠标位置

时间:2013-08-11 20:15:42

标签: java javafx javafx-2

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

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

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

rotated pane with black border

我该如何解决这个问题?

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

以下是一个例子:

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);
    }
}

2 个答案:

答案 0 :(得分:2)

<强>更新

问题已在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);
    }
}

答案 1 :(得分:0)

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

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

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

你可以为x,y,z轴做到这一点:

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

将此移位减去你得到的指针的位置

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

以下代码对我有用(但也许它不能很好地重现您的问题)。

public class JFXRotationXOrds扩展Application {

@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);
}
}