How to get location of mouse in JavaFX?


Question

I am a beginner in java(fx).
How do you get the mouse location in x and y in JavaFX? I tried using AWT's MouseInfo(also imported it), but it's not working. I also saw the code for it in Ensembles(that dragging the ball-window in "advanced stage", that's what I need to do, drag my undecorated JavaFX stage), but it also doesn't work. I am using FXML with controller, and I guess that's the main problem. Should I switch back to the single-file simple JavaFX? I know FXML is better for laying out the UI, but I can't get many of such codes to work. Or do I need some other sort of code for my controller? Please give proper codes with comments wherever possible.
If you need a bit of my code to inspect, feel free to ask.

1
7
5/19/2013 2:08:06 PM

There are a few items in your question - I'll tackle them one at a time.

How do you get the mouse location in x and y in JavaFX?

Add a mouse event handler to the appropriate JavaFX component that you want to track the mouse location in. A JavaFX mouse event will report multiple different kinds of co-ordinates. The x and y co-ordinates are relative to the top left corner of the node whose location is being monitored. The sceneX and sceneY co-ordinates are relative to the scene's top left 0,0 co-ordinates. The screenX and screenY co-ordinates are relative to the top left 0,0 co-ordinates of the current screen.

These co-ordinates are documented in the MouseEvent documentation. There is extra information in understanding co-ordinate systems in the Node and Scene documentation.

mouselocationmonitor

import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.event.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;
import javafx.stage.*;

public class MouseLocationReporter extends Application {
  private static final String OUTSIDE_TEXT = "Outside Label";

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

  @Override public void start(final Stage stage) {
    final Label reporter = new Label(OUTSIDE_TEXT);
    Label monitored = createMonitoredLabel(reporter);

    VBox layout = new VBox(10);
    layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 10px;");
    layout.getChildren().setAll(
      monitored,
      reporter
    );
    layout.setPrefWidth(500);

    stage.setScene(
      new Scene(layout)
    );

    stage.show();
  }

  private Label createMonitoredLabel(final Label reporter) {
    final Label monitored = new Label("Mouse Location Monitor");

    monitored.setStyle("-fx-background-color: forestgreen; -fx-text-fill: white; -fx-font-size: 20px;");

    monitored.setOnMouseMoved(new EventHandler<MouseEvent>() {
      @Override public void handle(MouseEvent event) {
        String msg =
          "(x: "       + event.getX()      + ", y: "       + event.getY()       + ") -- " +
          "(sceneX: "  + event.getSceneX() + ", sceneY: "  + event.getSceneY()  + ") -- " +
          "(screenX: " + event.getScreenX()+ ", screenY: " + event.getScreenY() + ")";

        reporter.setText(msg);
      }
    });

    monitored.setOnMouseExited(new EventHandler<MouseEvent>() {
      @Override public void handle(MouseEvent event) {
        reporter.setText(OUTSIDE_TEXT);
      }
    });

    return monitored;
  }
}

I tried using AWT's MouseInfo(also imported it), but it's not working.

Don't do this. Mixing different graphical toolkits (for example Swing/AWT and JavaFX) is an advanced topic. In general, if you are writing a JavaFX application, avoid importing anything from the java.awt namespace and the javax.swing namespace. You only really need to use those if you have a large, existing Swing based application or framework that you need to inter-operate with your JavaFX application. In this case, you don't have that situation.

I also saw the code for it in Ensembles(that dragging the ball-window in "advanced stage", that's what I need to do, drag my undecorated JavaFX stage), but it also doesn't work.

I tried the Ensemble Advanced Stage sample and dragging that stage around worked for me.

Another sample for dragging an undecorated stage in JavaFX is in the answer to How to draw a clock with JavaFX 2? which has associated sample code. The method used to make the undecorated stage draggable for the clock sample is:

/** makes a stage draggable using a given node */
public static void makeDraggable(final Stage stage, final Node byNode) {
  final Delta dragDelta = new Delta();
  byNode.setOnMousePressed(new EventHandler<MouseEvent>() {
    @Override public void handle(MouseEvent mouseEvent) {
      // record a delta distance for the drag and drop operation.
      dragDelta.x = stage.getX() - mouseEvent.getScreenX();
      dragDelta.y = stage.getY() - mouseEvent.getScreenY();
      byNode.setCursor(Cursor.MOVE);
    }
  });
  byNode.setOnMouseReleased(new EventHandler<MouseEvent>() {
    @Override public void handle(MouseEvent mouseEvent) {
      byNode.setCursor(Cursor.HAND);
    }
  });
  byNode.setOnMouseDragged(new EventHandler<MouseEvent>() {
    @Override public void handle(MouseEvent mouseEvent) {
      stage.setX(mouseEvent.getScreenX() + dragDelta.x);
      stage.setY(mouseEvent.getScreenY() + dragDelta.y);
    }
  });
  byNode.setOnMouseEntered(new EventHandler<MouseEvent>() {
    @Override public void handle(MouseEvent mouseEvent) {
      if (!mouseEvent.isPrimaryButtonDown()) {
        byNode.setCursor(Cursor.HAND);
      }
    }
  });
  byNode.setOnMouseExited(new EventHandler<MouseEvent>() {
    @Override public void handle(MouseEvent mouseEvent) {
      if (!mouseEvent.isPrimaryButtonDown()) {
        byNode.setCursor(Cursor.DEFAULT);
      }
    }
  });
}

I am using FXML with controller, and I guess that's the main problem. Should I switch back to the single-file simple JavaFX? I know FXML is better for laying out the UI, but I can't get many of such codes to work.

Lack of understanding and familiarity with the underlying JavaFX APIs is probably your main problem rather than use of FXML. However the additional complexity fxml implies together with the lighter documentation and samples for it on the web may be contributing to your hardships. If use of FXML is making it difficult for you to understand how to get some JavaFX functions to work, I advise to stop using FXML for now. Code the logic by hand using the Java APIs and refer to the Oracle JavaFX tutorials and the Ensemble sample code when you encounter things which are difficult for you.

Once you are comfortable coding directly to the JavaFX API, switch back to using FXML for larger projects which contain many GUI elements. The FXML elements and attributes themselves are built almost completely upon reflection of the standard JavaFX APIs. So, if you understand the core JavaFX APIs, you also understand almost everything about FXML.

Please do not post follow up comments to this answer (as this answer is long enough as it is). If you have new questions, create a new question (one question per question).

24
5/23/2017 12:01:43 PM

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon