Get the position of the mouse on the node relative to its coordinates and transformations

I have a 3D scene and I have a panel inside the scene that has rotational transformation on the x axis, I want to use this panel as a strategic playing field, but I have a problem.

When I enter the mouse inside the panel, this gives me the wrong cursor position.

For example, when I enter the mouse from the upper left corner (red circle) inside the panel (the rotated panel with a black border), it should show me (0,0) the cursor position inside the panel, but it shows something like (200, 400) .

rotated pane with black border

How can I solve this problem?

OR, in other words, how can I get the mouse coordinate on a node relative to a node and its transformation?

Here is an example:

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); } } 
+4
source share
2 answers

Update

The issue has been fixed in the JDK8 Early Access Release . You can either download this version or wait until it comes out. This was recorded in February as part of this ticket: RT-28129

Edited

I entered a JavaFX Jira ticket. You can follow him to see status updates.

I updated the demo to reflect your problem. This seemed to work when the transform used the z axis (yesterday is great for me today), but not when the transform was on the X or Y axis.

Hope this helps you.

 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); } } 
+2
source

Since you have not published any of your codes, this may seem obvious, but have you added a mouse event handler to the panel? If so (in my attempt to recreate your problem), the event.getX () and event.getY () methods returned an exepected position.

(did you use getSceneX () and getSceneY ()? in this case change to getX () and getY ())

Another way is to correct the position of the mouse that you get (position on stage) by the position of your panel.

you can do this for the x, y, z axes:

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

then subtract this shift to the position of the pointer that you get

Edit:. Looking at your code, it seems that you are adding a MouseEvent handler to the root object. Therefore, the event is fired when the mouse is on the root object. If you add it to your rectangle, for example, the mouse position will be relative to the rectangle.

The following code works for me (but maybe it doesnโ€™t reproduce your problem well).

open class JFXRotationXOrds extends 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); } } 
0
source

Source: https://habr.com/ru/post/1496456/


All Articles