0

I was wondering if there is a possibility to implement Sticky Headers on a GridPane in JavaFX, meaning a row of the GridPane that stays in place while you can scroll through the remaining rows of the pane.

Samarek
  • 444
  • 1
  • 8
  • 22

1 Answers1

2

It's possible, but you need to ensure the header nodes are the last children of the GridPane.children list. This allows you to set the translateY property of the header nodes to remain at the top of the ScrollPane wrapping the GridPane:

GridPane grid = new GridPane();

// fill grid
Color[] colors = new Color[]{Color.RED, Color.ORANGE, Color.LIGHTGREEN, Color.LIGHTBLUE};
for (int i = 1; i <= 100; i++) {
    grid.add(new Rectangle(50, 50, colors[(2 * i - 2) % colors.length]), 0, i);
    grid.add(new Label(Integer.toString(2 * i - 1)), 0, i);
    grid.add(new Rectangle(50, 50, colors[(2 * i - 1) % colors.length]), 1, i);
    grid.add(new Label(Integer.toString(2 * i)), 1, i);
}

// create & add header
Node[] headers = new Node[] {
    createHeaderNode("H1"),
    createHeaderNode("H2")
};
grid.addRow(0, headers);

ScrollPane scrollPane = new ScrollPane(grid);
scrollPane.setPrefHeight(400);

// keep header in position on top of the viewport
InvalidationListener headerUpdater = o -> {
    final double ty = (grid.getHeight() - scrollPane.getViewportBounds().getHeight()) * scrollPane.getVvalue();
    for (Node header : headers) {
        header.setTranslateY(ty);
    }
};
grid.heightProperty().addListener(headerUpdater);
scrollPane.viewportBoundsProperty().addListener(headerUpdater);
scrollPane.vvalueProperty().addListener(headerUpdater);
private static Label createHeaderNode(String text) {
    Label label = new Label(text);
    label.setMaxWidth(Double.MAX_VALUE);
    label.setStyle("-fx-border-style: solid; -fx-background-color: white;");
    return label;
}
fabian
  • 80,457
  • 12
  • 86
  • 114