代码之家  ›  专栏  ›  技术社区  ›  Jai

javafx:如何使tilepane居中,但将tilepane子元素从左到右放置?

  •  1
  • Jai  · 技术社区  · 6 年前

    就像标题所暗示的,我试着把 TilePane 在其父容器中,但同时,我希望 替利泮 从左到右放置。

    @Override
    public void start(final Stage primaryStage) throws Exception {
        final VBox root = new VBox();
        final Scene sc = new Scene(root);
        primaryStage.setScene(sc);
    
        final TilePane tp = new TilePane();
        root.getChildren().add(tp);
    
        tp.setPrefColumns(3);
        tp.setAlignment(Pos.TOP_LEFT);
        tp.setStyle("-fx-background-color: green;");
        root.setAlignment(Pos.CENTER);
        root.setFillWidth(true);
    
        Stream.iterate(0, i -> i + 1).limit(5).forEach(i -> {
            Region r = new Region();
            r.setPrefSize(200, 200);
            r.setStyle("-fx-background-color: red; -fx-border-color: blue; -fx-border-width: 1;");
    
            tp.getChildren().add(r);
        });
    
        primaryStage.show();
    }
    

    这将创建如下窗口:

    On launch

    增加窗口宽度会导致:

    Increased width

    继续增加窗口高度会导致:

    Increased height

    设置 root.setFillWidth(false) 原因:

    Fill width = false

    我能做些什么来确保 替利泮 保持居中,而 Region 子节点继续从每行的左侧放置?

    更新

    更清楚地说, 替利泮 在调整大小期间,应该尝试在除顶行之外的所有行中容纳尽可能多的平铺(本例中是区域)。换句话说,第一排右边不应该有任何绿地。或者,左边和右边的绿地应该相等。此外,瓷砖必须从左到右放置。设置 TilePane.setAlignment(Pos.CENTER) 会在最后一行的中心放置任何“剩余”瓷砖,这是不可接受的。

    1 回复  |  直到 6 年前
        1
  •  2
  •   Jai    6 年前

    通过 TilePane 是的。阻止父级调整 替利泮 超出了它的首选大小设置 fillWidth false 用一个倾听者 width 财产 VBox 设置 prefColumns 财产

    @Override
    public void start(Stage primaryStage) {
        final VBox root = new VBox();
        final Scene sc = new Scene(root);
        primaryStage.setScene(sc);
    
        final TilePane tp = new TilePane();
        tp.setPrefTileWidth(200);
        tp.setPrefTileHeight(200);
        root.getChildren().add(tp);
    
        tp.setPrefColumns(3);
        tp.setAlignment(Pos.TOP_LEFT);
        tp.setStyle("-fx-background-color: green;");
        root.setAlignment(Pos.CENTER);
        root.setFillWidth(false);
    
        // set prefColumns from a listener instead of a binding
        // to prevent the initial value from being set to 0
        root.widthProperty().addListener((o, oldValue, newValue) -> {
            // allow as many columns as fit the parent but keep it in
            // range [1, childCount]
            tp.setPrefColumns(Math.min(tp.getChildren().size(),
                    Math.max(1, (int) (newValue.doubleValue() / tp.getPrefTileWidth()))));
        });
    
        Stream.iterate(0, i -> i + 1).limit(5).forEach(i -> {
            Region r = new Region();
            r.setStyle("-fx-background-color: red; -fx-border-color: blue; -fx-border-width: 1;");
    
            tp.getChildren().add(r);
        });
    
        primaryStage.show();
    }
    

    按操作更新

    我很惊讶这种方法,我尝试了一些稍微有活力的方法。

    root.widthProperty().addListener((o, oldValue, newValue) -> {
        double maxWidth = tp.getChildren()
                            .stream()
                            .filter(n -> n instanceof Region)
                            .map(n -> ((Region) n).getWidth())
                            .max(Double::compareTo)
                            .orElse(0d);
    
        tp.setPrefColumns(Math.min(tp.getChildren().size(),
                Math.max(1, (int) (newValue.doubleValue() / maxWidth))));
    });
    
    Stream.iterate(0, i -> i + 1).limit(5).forEach(i -> {
        Region r = new Region();
        Random random = new Random();
        r.setPrefSize(random.nextInt(150) + 50, random.nextInt(150) + 50);
        System.out.println(r.getPrefWidth());
        System.out.println(r.getPrefHeight());
        r.setStyle("-fx-background-color: red; -fx-border-color: blue; -fx-border-width: 1;");
    
        tp.getChildren().add(r);
    });
    

    这样就不需要为每个平铺设置静态宽度/高度。

    虽然这在这个基本示例中有效,但我已经在更复杂的平铺子对象上尝试过。