The difference between the actual (phisycal) clicking and your programmatic clicking is, that in the first case the original event target is bluePane
(as it is the "uppermost" Node
visually), in the latter case the target is yellowPane
.
So, when the route construction occurs (please refer to the Event Delivery Process section) in the first case the route will be root
-> yellowPane
-> bluePane
, and in the second case it will be only root
-> yellowPane
, hence the bluePane
is untouched by the event.
Based on this you can target the bluePane
:
Event.fireEvent(bluePane, new MouseEvent(MouseEvent.MOUSE_CLICKED,
sceneCoords.getX(), sceneCoords.getY(), screenCoords.getX(), screenCoords.getY(), MouseButton.PRIMARY, 1,
true, true, true, true, true, true, true, true, true, true, null));
Or you can use a Robot
for example to generate the click:
try {
robot = new java.awt.Robot();
robot.mouseMove((int)screenCoords.getX(), (int)screenCoords.getY());
robot.mousePress(16);
robot.mouseRelease(16);
robot.mouseMove((int) originalLocation.getX(), (int)originalLocation.getY());
} catch (AWTException e) {
e.printStackTrace();
}
Update 1:
If you want to stick with the JavaFX way, the question is now how to determine the "uppermost" Node
on a position.
This is one thing that is not possible in a clean way. There is already a feature request about this.
I have found this on helper method on fxexperience that can be used to determinte the Node
on a certain position:
public static Node pick(Node node, double sceneX, double sceneY) {
Point2D p = node.sceneToLocal(sceneX, sceneY, true /* rootScene */);
// check if the given node has the point inside it, or else we drop out
if (!node.contains(p)) return null;
// at this point we know that _at least_ the given node is a valid
// answer to the given point, so we will return that if we don't find
// a better child option
if (node instanceof Parent) {
// we iterate through all children in reverse order, and stop when we find a match.
// We do this as we know the elements at the end of the list have a higher
// z-order, and are therefore the better match, compared to children that
// might also intersect (but that would be underneath the element).
Node bestMatchingChild = null;
List<Node> children = ((Parent)node).getChildrenUnmodifiable();
for (int i = children.size() - 1; i >= 0; i--) {
Node child = children.get(i);
p = child.sceneToLocal(sceneX, sceneY, true /* rootScene */);
if (child.isVisible() && !child.isMouseTransparent() && child.contains(p)) {
bestMatchingChild = child;
break;
}
}
if (bestMatchingChild != null) {
return pick(bestMatchingChild, sceneX, sceneY);
}
}
return node;
}
that you can use like:
Node pick = pick(root, sceneCoords.getX(), sceneCoords.getY());
Event.fireEvent(pick, new MouseEvent(MouseEvent.MOUSE_CLICKED,
sceneCoords.getX(), sceneCoords.getY(), screenCoords.getX(), screenCoords.getY(), MouseButton.PRIMARY, 1,
true, true, true, true, true, true, true, true, true, true, null));
Update2:
You can also use the deprecated method Node.impl_pickNode(PickRay pickRay, PickResultChooser result)
to get the intersected Node
on a scene position:
PickRay pickRay = new PickRay((int) sceneCoords.getX(), (int) sceneCoords.getY(), 1.0, 1.0, 1.0);
PickResultChooser pickResultChooser = new PickResultChooser();
root.impl_pickNode(pickRay, pickResultChooser);
Node intersectedNode = pickResultChooser.getIntersectedNode();
You can use also this Node
as target similarly.