JavaFX ScrollPane programmatically moving the viewport - centering content

后端 未结 3 1632
时光取名叫无心
时光取名叫无心 2021-01-05 13:11

I can use the setVvalue(double) and setHvalue(double) methods to move a viewport in a JavaFX ScrollPane. What I\'m struggling to do is center a particular node in the conte

3条回答
  •  北荒
    北荒 (楼主)
    2021-01-05 14:00

    I'll try explaining this without code, because I don't think that's necessary here.

    Let's say the content of your scrollpane has height h, and the height of the viewport is v. If h = v, then the content would fit perfectly into the viewport, and you would need no scrollbar. In this situation (with a non-movable scrollbar), for an element to be centered, it would need to be positioned at the center of the scrollpane's content. You can't move it to the viewport's center by means of scrolling.

    Now consider h to be twice the size of v (i.e. h = 2v). In this situation the upper 1/4 and the lower 1/4 of the scrollpane's content could not be centered by scrolling.

    (If you absolutely needed to center any component by scrolling you should consider padding your content pane, but we'll continue with the unpadded solution here)

    When you think about it, you'll realize the possible scrollable distance of the scrollbar is h - v, and you will scroll that amount by setting vvalue to 1.0.

    To center a point y (here the point y is a coordinate of the scrollpane's content pane) you can use the following vvalue:

    vvalue = (y - 0.5 * v) / (h - v) 
    

    The nominator of this expression is the y-coordinate of what is shown at the top of the viewport when the point y is centered inside the viewport. The denominator is the total scrollable distance.

    Edit: Adding some code anyway!

    public void centerNodeInScrollPane(ScrollPane scrollPane, Node node) {
        double h = scrollPane.getContent().getBoundsInLocal().getHeight();
        double y = (node.getBoundsInParent().getMaxY() + 
                    node.getBoundsInParent().getMinY()) / 2.0;
        double v = scrollPane.getViewportBounds().getHeight();
        scrollPane.setVvalue(scrollPane.getVmax() * ((y - 0.5 * v) / (h - v)));
    }
    

    (Please note this assumes that the node is a direct child of the scrollpane's contentpane)

    Hope this helps! :)

提交回复
热议问题