如何使javafx 8滚动窗格的内容居中

问题描述 投票:5回答:4

我有一个ScrollPane,它包含一个GridPane,其中包含一个ImageView,其中包含一个Image。我想要的是Image在GridPane中居中。

没有ScrollPane,我可以使用setAlignment(Pos.TOP_CENTER)完成此操作,但是一旦我将GridPane添加到ScrollPane,Image就会显示在左上角。

如何让ScrollPane使用setAlignment()值或手动居中Image?

---示例编辑---

没有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();
  }
}

结果:https://i.imgur.com/eWvBQy6.png

带滚动窗格的代码:

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

结果:https://i.imgur.com/1aJDX4m.png

javafx-8
4个回答
5
投票

发生的事情是,当网格窗格以滚动窗格为中心时,图像视图位于滚动窗格的左上角。

一种解决方法是将图像视图包装在堆栈窗格(默认居中)中,并确保堆栈窗格至少与滚动窗格的视口一样宽:

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

7
投票

虽然imageHolder.minWidthProperty().bind(Bindings.createDoubleBinding(() -> scroll.getViewportBounds().getWidth(), scroll.viewportBoundsProperty()));确实可以解决问题,但似乎存在一些问题(例如,有时会出现错误的滚动条/闪烁内容等)。

我发现一个简单的scroll.setFitToWidth(true);(和/或scroll.setFitToHeight(true);)也保持内容大小与滚动窗格,但没有上述问题!


0
投票

更好地解决视口边界属性:

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
投票

在某些情况下这可能有所帮助:

<ScrollPane fitToWidth="true" fitToHeight="true">
© www.soinside.com 2019 - 2024. All rights reserved.