在ScrollPane中使用TilePane进行响应式UI设计

时间:2016-08-17 10:48:16

标签: javafx javafx-2 javafx-8 scrollpane

我试图把头围绕着Scroll-和Tilepanes atm,我遇到了一个问题,我只能在没有肮脏黑客的情况下解决。

我有一个水平TilePane有8个Tiles,我把它设置为4列,产生2行4个tile。 那个TilePane我放入了一个HBox,因为如果我把它放在StackPane中,它会拉伸tilepane的大小,使我的colum设置为void。有点奇怪的是,设置prefColumns / Rows重新计算TilePane的大小,而不是试图设置实际的列/行数量,感觉更像是一个肮脏的黑客。

无论如何,将HBox直接放入ScrollPane也不会起作用,因为即使在第二排瓷砖被切断之后,Scrollbars也不会出现。在Stackpane中再次设置HBox然后放入ScrollPane就可以了。至少我将窗口的宽度调整到如此之小以至于瓷砖必须重新对齐瓷砖并且出现第3行或更多行。

这是基本的程序:

var items = map(myData, property("items"));

我设法实现了我想要的行为,但它更像是一个非常脏的黑客。我在包含TilePane的HBox的高度和宽度上添加了一个监听器,并假设当高度改变时,因为宽度变得很小,以至于删除了一列并添加了一个新行。为了能够做到这一点,我将HBox放在VBox中,这样它就不会随着ScrollPane的高度而增长。对于宽度,我只是计算出是否有空间来显示另一个列(最多4个),就可以了。

以下是更改:

public class Main extends Application {

    @Override
    public void start(Stage stage) {

        TilePane tilePane = new TilePane();
        tilePane.setPadding(new Insets(5));
        tilePane.setVgap(4);
        tilePane.setHgap(4);
        tilePane.setPrefColumns(4);
        tilePane.setStyle("-fx-background-color: lightblue;");

        HBox tiles[] = new HBox[8];
        for (int i = 0; i < 8; i++) {
            tiles[i] = new HBox(new Label("This is node #" + i));
            tiles[i].setStyle("-fx-border-color: black;");
            tiles[i].setPadding(new Insets(50));
            tilePane.getChildren().add(tiles[i]);
        }

        HBox hbox = new HBox();
        hbox.setAlignment(Pos.CENTER);
        hbox.setStyle("-fx-background-color: blue;");
        hbox.getChildren().add(tilePane); 

        StackPane stack = new StackPane();
        stack.getChildren().add(hbox);

        ScrollPane sp = new ScrollPane();
        sp.setFitToHeight(true);
        sp.setFitToWidth(true);
        sp.setContent(stack);

        stage.setScene(new Scene(sp, 800, 600));
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }
}

然而,这种方法需要我

  

1.了解Tilepane中瓷砖的宽度。

     

2.考虑到瓷砖之间的填充和间隙,我的计算是准确的,我在这个例子中没有这样做。

如果你问我,它无论如何都不是一个好方法。这样一个基本的东西过程太复杂了。必须有一种更好,更简单的方法来完成ScrollPane中TilePanes的完全可恢复性和想要的行为。

1 个答案:

答案 0 :(得分:2)

TilePane中设置首选列数和/或行数决定了该磁贴窗格的prefWidthprefHeight值的计算。如果要强制使用最大列数,则只需要使maxWidth等于计算出的prefWidth:您可以使用

执行此操作
tilePane.setMaxWidth(Region.USE_PREF_SIZE);

这意味着(只要将窗格窗格放置在管理布局的内容中),它就永远不会比pref宽度宽,后者被计算为允许首选列数。当然,它可能比那个小。 (注意,如果您需要最少的列数而不是最大列数,则可以使用与setMinWidth相同的技巧。)

滚动窗格的fitToHeightfitToWidth属性将为true,尝试将内容的高度(分别为宽度)调整为等于滚动窗格视口的高度(宽度)。这些操作优先于内容的首选高度(宽度),但会尝试遵守最小高度(宽度)。

因此,同时调用setFitToWidth(true)setFitToHeight(true)通常是错误的,因为这几乎总是会完全关闭滚动(只是强制内容与滚动窗格的视口大小相同)。

所以在这里你要让tile窗格的最大宽度与pref宽度相对应,并将tile窗格的宽度固定为滚动窗格视口的宽度(这样当你缩小窗口的宽度时,它会缩小视口的宽度并创建更多列)。如果行数足够大,这将添加一个垂直滚动条,如果视口水平缩小到平铺窗格的最小宽度(计算为所有节点的首选宽度的最小值),则仅添加水平滚动条包含)。

我认为以下版本的原始代码基本上可以满足您的需求:

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Region;
import javafx.scene.layout.TilePane;
import javafx.stage.Stage;

public class ScrollingTilePane extends Application {

    @Override
    public void start(Stage stage) {

        TilePane tilePane = new TilePane();
        tilePane.setPadding(new Insets(5));
        tilePane.setVgap(4);
        tilePane.setHgap(4);
        tilePane.setPrefColumns(4);
        tilePane.setStyle("-fx-background-color: lightblue;");

        // dont grow more than the preferred number of columns:
        tilePane.setMaxWidth(Region.USE_PREF_SIZE);

        HBox tiles[] = new HBox[8];
        for (int i = 0; i < 8; i++) {
            tiles[i] = new HBox(new Label("This is node #" + i));
            tiles[i].setStyle("-fx-border-color: black;");
            tiles[i].setPadding(new Insets(50));
            tilePane.getChildren().add(tiles[i]);
        }

        HBox hbox = new HBox();
        hbox.setAlignment(Pos.CENTER);
        hbox.setStyle("-fx-background-color: blue;");
        hbox.getChildren().add(tilePane); 

//        StackPane stack = new StackPane();
//        stack.getChildren().add(tilePane);
//        stack.setStyle("-fx-background-color: blue;");

        ScrollPane sp = new ScrollPane();
//        sp.setFitToHeight(true);
        sp.setFitToWidth(true);
        sp.setContent(hbox);

        stage.setScene(new Scene(sp, 800, 600));
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }
}

请注意,如果您需要更改滚动窗格内容外部空间的背景颜色,则可以在外部样式表中使用以下颜色:

.scroll-pane .viewport {
  -fx-background-color: red ;
}