How to center javafx 8 scroll content

I have a ScrollPane that contains a GridPane that contains an ImageView that contains an image. I want the image to be centered in GridPane.

Without ScrollPane, I was able to accomplish this with setAlignment (Pos.TOP_CENTER), however, as soon as I added a GridPane to the ScrollPane, the image was displayed in the upper left corner.

How do I get ScrollPane to use the value of setAlignment () or manually center the image?

--- editing example ---

code without scrollpane:

public class ImageDB extends Application { @Override public void start(Stage root) { Image image = new Image("0.jpg"); ImageView view = new ImageView(); view.setImage(image); GridPane grid = new GridPane(); grid.getChildren().add(view); grid.setAlignment(Pos.TOP_CENTER); BorderPane border = new BorderPane(); border.setCenter(grid); root.setScene(new Scene(border)); root.setMaximized(true); root.show(); } } 

Result: https://i.imgur.com/eWvBQy6.png

code with scrollpane:

 public class ImageDB extends Application { @Override public void start(Stage root) { Image image = new Image("0.jpg"); ImageView view = new ImageView(); view.setImage(image); ScrollPane scroll = new ScrollPane(); scroll.setContent(view); GridPane grid = new GridPane(); grid.getChildren().add(scroll); grid.setAlignment(Pos.TOP_CENTER); BorderPane border = new BorderPane(); border.setCenter(scroll); root.setScene(new Scene(border)); root.setMaximized(true); root.show(); } } 

Result: https://i.imgur.com/1aJDX4m.png

+5
source share
4 answers

What happens when the grid panel centers the scroll panel, the image is viewed in the upper left corner of the scroll panel.

One fix is ​​to wrap the image on the stack stack (which is centered by default) and make sure that the stack area is no less than the width of the scroll bar view:

SSCCE:

 import javafx.application.Application; import javafx.beans.binding.Bindings; import javafx.geometry.HPos; import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.ScrollPane; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.BorderPane; import javafx.scene.layout.GridPane; import javafx.scene.layout.Priority; import javafx.scene.layout.StackPane; import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; import javafx.stage.Stage; public class ImageDB extends Application { @Override public void start(Stage root) { // Image image = new Image("0.jpg"); Image image = createImage(); ImageView view = new ImageView(); view.setImage(image); StackPane imageHolder = new StackPane(view); ScrollPane scroll = new ScrollPane(); scroll.setContent(imageHolder); GridPane grid = new GridPane(); imageHolder.minWidthProperty().bind(Bindings.createDoubleBinding(() -> scroll.getViewportBounds().getWidth(), scroll.viewportBoundsProperty())); grid.getChildren().add(imageHolder); // grid.setAlignment(Pos.TOP_CENTER); BorderPane border = new BorderPane(); border.setCenter(scroll); root.setScene(new Scene(border)); root.setMaximized(true); root.show(); } private Image createImage() { return new Rectangle(400, 200, Color.CORNFLOWERBLUE).snapshot(null, null); } public static void main(String[] args) { launch(args); } } 
+3
source

Although imageHolder.minWidthProperty().bind(Bindings.createDoubleBinding(() -> scroll.getViewportBounds().getWidth(), scroll.viewportBoundsProperty())); really does the trick, it seems to have some problems with it (for example, sometimes incorrect scrollbars / flickering content are displayed, etc.).

I found that simple scroll.setFitToWidth(true); (and / or scroll.setFitToHeight(true); ) also saves content the size of a scroll bar, but without the aforementioned problems!

+7
source

Best solution through viewportBoundsProperty:

 import javafx.application.Application; import javafx.geometry.Bounds; import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.control.ScrollPane; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.BorderPane; import javafx.scene.layout.GridPane; import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; import javafx.stage.Stage; public class ImageDB extends Application { final static int WIDTH = 400; final static int HEIGHT = 200; @Override public void start(Stage root) { // Image image = new Image("0.jpg"); Image image = this.createImage(); ImageView view = new ImageView(); view.setImage(image); GridPane grid = new GridPane(); grid.getChildren().add(view); ScrollPane scroll = new ScrollPane(); scroll.setContent(grid); BorderPane border = new BorderPane(); border.setCenter(scroll); this.center(scroll.getViewportBounds(), grid); scroll.viewportBoundsProperty().addListener((observable, oldValue, newValue) -> { this.center(newValue, grid); }); root.setScene(new Scene(border)); root.setMaximized(true); root.show(); } private Image createImage() { return new Rectangle(ImageDB.WIDTH, ImageDB.HEIGHT, Color.CORNFLOWERBLUE).snapshot(null, null); } public static void main(String[] args) { Application.launch(args); } private void center(Bounds viewPortBounds, Node centeredNode) { double width = viewPortBounds.getWidth(); double height = viewPortBounds.getHeight(); if (width > ImageDB.WIDTH) { centeredNode.setTranslateX((width - ImageDB.WIDTH) / 2); } else { centeredNode.setTranslateX(0); } if (height > ImageDB.HEIGHT) { centeredNode.setTranslateY((height - ImageDB.HEIGHT) / 2); } else { centeredNode.setTranslateY(0); } } } 
0
source

In some cases, this may help:

 <ScrollPane fitToWidth="true" fitToHeight="true"> 
0
source

All Articles