Reputation: 21
I have a pane, inside the pane I have a circle and a label. Everytime mouse enter or exit the circle, the label will change to "enter" or "exit". And the label will move accordingly to the mouse position (mouse scenceX and sceneY).
The problem is when I enter the mouse inside the circle, the label will change to "enter" but will immediately change to "exit" then.
I think there is an overlap eventhandler somewhere in my code, but I don't know why. This is my code:
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
Pane pane = new Pane();
pane.setStyle("-fx-background-color: grey;");
pane.setPrefSize(300,300);
Circle circle = new Circle();
circle.setFill(Color.TRANSPARENT);
int radius = 50;
circle.setRadius(radius);
circle.setStroke(Color.BLACK);
circle.setStrokeWidth(2);
circle.setLayoutX(100);
circle.setLayoutY(60);
pane.getChildren().add(circle);
Label label = new Label("Mouse point is outside the circle");
pane.getChildren().add(label);
circle.addEventHandler(MouseEvent.MOUSE_EXITED, e -> {
label.setText("Mouse point is outside the circle");
System.out.println("exit");
});
circle.addEventHandler(MouseEvent.MOUSE_ENTERED, e -> {
label.setText("Mouse point is inside the circle");
System.out.println("enter");
});
pane.addEventFilter(MouseEvent.MOUSE_MOVED, e -> {
label.setLayoutX(e.getSceneX());
label.setLayoutY(e.getSceneY());
});
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(pane));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Upvotes: 2
Views: 69
Reputation: 209714
As explained in another answer, when the label moves, it moves so that the mouse is now inside the label; this means it is no longer hovering directly over the circle, so an "exited" event is fired on the circle.
The simplest fix is just to make the label ignore the mouse, which can be done using the mouseTransparent
property:
Label label = new Label("Mouse point is outside the circle");
label.setMouseTransparent(true);
pane.getChildren().add(label);
Upvotes: 1
Reputation: 20924
I'm only guessing but I believe the problem is that when the event filter for pane
is executed, the result is that the mouse pointer moves from being inside circle
to inside label
. Then when you move the mouse, it leaves label
and enters circle
which causes the MOUSE_ENTERED
event handler to fire. After that handler fires, the event filter fires which moves the mouse pointer out of circle
and into label
which causes MOUSE_EXITED
event handler to fire. That's why you see enter and exit repeatedly when you move the mouse pointer around inside circle
. You don't see enter nor exit at all when you move the mouse pointer around pane
when it is outside of circle
.
In order to fix it, I removed MOUSE_ENTERED
and MOUSE_EXITED
and inside the event filter, I check whether the mouse pointer is inside the bounds of circle
and set label
text accordingly.
Here is the code.
(Note that I replaced addEventFilter
with setOnMouseMoved
.)
import javafx.application.Application;
import javafx.geometry.Bounds;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
Pane pane = new Pane();
pane.setStyle("-fx-background-color: grey;");
pane.setPrefSize(300, 300);
Label label = new Label("Mouse point is outside the circle");
Circle circle = new Circle();
circle.setFill(Color.TRANSPARENT);
int radius = 50;
circle.setRadius(radius);
circle.setStroke(Color.BLACK);
circle.setStrokeWidth(2);
circle.setLayoutX(100);
circle.setLayoutY(60);
Bounds boundingBox = circle.getBoundsInParent();
double maxX = boundingBox.getMaxX();
double minX = boundingBox.getMinX();
double maxY = boundingBox.getMaxY();
double minY = boundingBox.getMinY();
pane.getChildren().add(circle);
pane.getChildren().add(label);
pane.setOnMouseMoved(e -> {
double x = e.getSceneX();
double y = e.getSceneY();
if (minX < x && x < maxX && minY < y && y < maxY) {
label.setText("Mouse point is inside the circle");
}
else {
label.setText("Mouse point is outside the circle");
}
label.setLayoutX(e.getSceneX());
label.setLayoutY(e.getSceneY());
});
primaryStage.setTitle("Hello World");
Scene scene = new Scene(pane);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Upvotes: 1