Javafx 如何调整滚动窗格以使其子节点之一在视口中可见?

Javafx 如何调整滚动窗格以使其子节点之一在视口中可见?,javafx,java-8,javafx-8,Javafx,Java 8,Javafx 8,我正在试图弄清楚如何滚动滚动窗格,这样嵌套在其内容中的任何节点都可以显示出来。目标节点可能有许多我无法预测的嵌套级别 这差不多是我能做到的最接近的了。它可以工作,但它是一个相当的黑客,并且有一个bug,在某些条件下会产生一个无休止的递归调用循环。一定有更好的办法 private void ensureVisible(ScrollPane scrollPane, Node node) { Bounds viewportBounds = scrollPane.localToScene(sc

我正在试图弄清楚如何滚动
滚动窗格
,这样嵌套在其内容中的任何
节点
都可以显示出来。目标
节点
可能有许多我无法预测的嵌套级别

这差不多是我能做到的最接近的了。它可以工作,但它是一个相当的黑客,并且有一个bug,在某些条件下会产生一个无休止的递归调用循环。一定有更好的办法

private void ensureVisible(ScrollPane scrollPane, Node node) {

    Bounds viewportBounds = scrollPane.localToScene(scrollPane.getBoundsInLocal());
    Bounds nodeBounds = node.localToScene(node.getBoundsInLocal());

    if (!viewportBounds.contains(nodeBounds)) {
        if (nodeBounds.getMaxY() > viewportBounds.getMaxY()) {
            // node is below of viewport
            scrollPane.setVvalue(scrollPane.getVvalue() + 0.01);

            if (scrollPane.getVvalue() != 1.0) {
                ensureVisible(scrollPane, node);
            }
        } else if (nodeBounds.getMinY() < viewportBounds.getMinY()) {
            // node is above of viewport
            scrollPane.setVvalue(scrollPane.getVvalue() - 0.01);

            if (scrollPane.getVvalue() != 0.0) {
                ensureVisible(scrollPane, node);
            }
        } else if (nodeBounds.getMaxX() > viewportBounds.getMaxX()) {
            // node is right of viewport
            scrollPane.setHvalue(scrollPane.getHvalue() + 0.01);

            if (scrollPane.getHvalue() != 1.0) {
                ensureVisible(scrollPane, node);
            }
        } else if (nodeBounds.getMinX() < viewportBounds.getMinX()) {
            // node is left of viewport
            scrollPane.setHvalue(scrollPane.getHvalue() - 0.01);

            if (scrollPane.getHvalue() != 0.0) {
                ensureVisible(scrollPane, node);
            }
        }
    }
}
private void可修改(滚动窗格滚动窗格,节点节点){
Bounds viewportBounds=scrollPane.localToScene(scrollPane.getBoundsInLocal());
Bounds nodeBounds=node.localToScene(node.getBoundsInLocal());
如果(!viewportBounds.contains(nodeBounds)){
if(nodeBounds.getMaxY()>viewportBounds.getMaxY()){
//节点位于视口的下方
scrollPane.setVvalue(scrollPane.getVvalue()+0.01);
如果(scrollPane.getVvalue()!=1.0){
确保可修改(滚动窗格、节点);
}
}else if(nodeBounds.getMinY()viewportBounds.getMaxX()){
//节点位于视口的右侧
scrollPane.setHvalue(scrollPane.getHvalue()+0.01);
如果(scrollPane.getHvalue()!=1.0){
确保可修改(滚动窗格、节点);
}
}else if(nodeBounds.getMinX()
只需将坐标从
节点的坐标系转换为内容的坐标系即可。根据内容大小、视口大小和变换后的坐标,可以确定滚动位置:

public static void scrollTo(ScrollPane scrollPane, Node node) {
    final Node content = scrollPane.getContent();
    Bounds localBounds = node.getBoundsInLocal();
    Point2D position = new Point2D(localBounds.getMinX(), localBounds.getMinY());

    // transform to content coordinates
    while (node != content) {
        position = node.localToParent(position);
        node = node.getParent();
    }

    final Bounds viewportBounds = scrollPane.getViewportBounds();
    final Bounds contentBounds = content.getBoundsInLocal();

    scrollPane.setHvalue(position.getX() / (contentBounds.getWidth() - viewportBounds.getWidth()));
    scrollPane.setVvalue(position.getY() / (contentBounds.getHeight() - viewportBounds.getHeight()));
}