How to center the content of a javafx 8 scrollpane

和自甴很熟 提交于 2019-12-30 06:41:13

问题


I have a ScrollPane, which contains a GridPane, which contains an ImageView, which contains an Image. What I want is for the Image to be centered in the GridPane.

Without the ScrollPane I was able to accomplish this with setAlignment(Pos.TOP_CENTER), however once I added the GridPane to the ScrollPane the Image was displayed in the upper-left corner.

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

---example edit---

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


回答1:


What's happening is that while the grid pane is centering the scroll pane, the image view is sitting at the top left of the scroll pane.

One fix is to wrap the image view in a stack pane (which centers by default), and make sure the stack pane is at least as wide as the scroll pane's viewport:

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);
  }
}



回答2:


While imageHolder.minWidthProperty().bind(Bindings.createDoubleBinding(() -> scroll.getViewportBounds().getWidth(), scroll.viewportBoundsProperty())); indeed does the trick, there seem to be some issues with it (e.g., sometimes showing erroneous scrollbars/flickering content, etc.).

I since found that a simple scroll.setFitToWidth(true); (and/or scroll.setFitToHeight(true);) also keeps the content sized with the scroll pane, but without the aforementioned issues!




回答3:


Better solution via 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);
        }

    }

}



回答4:


This could help in some cases:

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


来源:https://stackoverflow.com/questions/30687994/how-to-center-the-content-of-a-javafx-8-scrollpane

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!