Search code examples
javajavafx-2

JavaFX 2.2 get node at coordinates (visual tree hit testing)


How can I get a list of (or the first one of) the controls under the mouse/arbitrary coordinates? I know WPF has VisualTreeHelper.HitTest and it has a callback that can be used to filter out all the controls at a point. Is there something similar for JavaFX? (or different, I just care for the first element at a given point) I've seen lots of information to get coordinates of a node, but no information on how to get a node by coordinates.


Solution

  • Update Dec 2021

    The impl_pickNode function referred to in the answer was removed and replaced by alternate picking functionality.

    Similar functionality is demonstrated in the javafx.scene.Scene source, where there is a function just used for testing the JavaFX system:

    /**
     * Note: The only user of this method is in unit test: PickAndContainTest.
     */
    Node test_pick(double x, double y) {
        inMousePick = true;
        PickResult result = mouseHandler.pickNode(new PickRay(x, y, 1,
                Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
        inMousePick = false;
        if (result != null) {
            return result.getIntersectedNode();
        }
        return null;
    }
    

    This functionality is still private functionality within the JavaFX system, it is not exposed as a supported public API. So JavaFX internally knows how to do this and if you are willing to investigate the internal source and use internal APIs, break modularity and compromise backward compatibility, then you can probably get a result.


    You could use node.impl_pickNode(x,y).

    Documentation from the impl_pickNode method (copied from the source).

    /** 
     * Finds a top-most child node that contains the given coordinates.
     *
     * Returns the picked node, null if no such node was found.
     *
     * @deprecated This is an internal API that is not intended for use 
     *             and will be removed in the next version. 
     **/
    public final Node impl_pickNode(double parentX, double parentY)
    

    Note carefully the deprecation warning in the comment and use at your own risk.

    Update

    There is an existing feature request in the JavaFX issue tracker: FX should provide a Parent.pick() routine. This feature request is for a public picking API which will not be deprecated in the future. The requested feature is described as: "The routine could return a single Node or a list of all the Nodes below the mouse ordered by z coordinates". The feature is not scheduled for implementation until the "Van Ness" release which is the release after the initial JDK8 release (i.e. the feature won't be available until Christmas 2013 at the earliest).