2

I have two javafx.scene.shape.Box instances which are placed right adjacent to each other:

enter image description here

I would like to be notified whenever the picked node changes, i.e. whenever the mouse is entering or exiting the red or blue node.

Moving the mouse from black to any of the colored boxes correctly triggers a "mouse entered" event (and vice-versa, from red/blue to black fires a "mouse exited" event).

However, moving the mouse from red directly to blue (or from blue directly to red) does not trigger any events.

import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Box;
import javafx.stage.Stage;

public class Demo extends Application {

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

    @Override
    public void start(Stage stage) {
        Box redBox = new Box(100, 100, 100);
        redBox.setId("red");
        redBox.setMaterial(new PhongMaterial(Color.RED));
        redBox.setTranslateX(100);
        redBox.setTranslateY(100);
        redBox.setTranslateZ(20);

        Box blueBox = new Box(100, 100, 100);
        blueBox.setId("blue");
        blueBox.setMaterial(new PhongMaterial(Color.BLUE));
        blueBox.setTranslateX(200);
        blueBox.setTranslateY(100);
        blueBox.setTranslateZ(20);

        PointLight pointLight = new PointLight(Color.ANTIQUEWHITE);
        pointLight.setTranslateX(800);
        pointLight.setTranslateY(-100);
        pointLight.setTranslateZ(-1000);

        Group root = new Group(redBox, blueBox);
        root.getChildren().add(pointLight);

        root.setOnMouseEntered(me -> {
            System.out.println("Entered " + resolvePickedId(me));
        });

        root.setOnMouseExited(me -> {
            System.out.println("Exited " + resolvePickedId(me));
        });

        Scene scene = new Scene(root, 300, 200, true);
        scene.setFill(Color.rgb(10, 10, 40));
        scene.setCamera(new PerspectiveCamera(false));
        stage.setScene(scene);
        stage.show();
    }

    private static String resolvePickedId(MouseEvent me) {
        Node intersectedNode = me.getPickResult().getIntersectedNode();
        return intersectedNode == null ? "(none)" : intersectedNode.getId();
    }

}

What am I missing?

Rahel Lüthy
  • 6,837
  • 3
  • 36
  • 51

2 Answers2

2

You would have to add a MouseListener to blueBox and redBox instead of root. When you add the MouseListener to root you only get notified when leaving/entering root hence no event when changing the element inside your root element.

user432
  • 3,506
  • 17
  • 24
2

You set up a Group root of those two boxes, and whenever you enter or exit this group, your event gets triggered. Thats what is happening. Since both boxes are children of the Group, you won't get notified, because your Listener is looking for the Group, not for it's children.

Either you create a MouseListener directly to the boxes, or you can do something like track the current node, and check OnMouseMoved for a change:

//in the class, new variable
Node save = null;

//.... in the start method

root.setOnMouseEntered(me -> {
    System.out.println("Entered " + resolvePickedId(me));
    save = me.getPickResult().getIntersectedNode();
});

root.setOnMouseMoved(me ->{
    if(me.getPickResult().getIntersectedNode() != save){
        System.out.println("Changed to "+resolvePickedId(me));
        save = me.getPickResult().getIntersectedNode();
    }
});

root.setOnMouseExited(me -> {
    System.out.println("Exited " + resolvePickedId(me));
    save = null;
});
Loki
  • 4,065
  • 4
  • 29
  • 51