Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create table with vertical/column header in JavaFX

Tags:

javafx

Is there a way to create tableview with vertical headings ? I don't see any option in javafx to do this.

like image 587
Saddam Hussain I H Avatar asked Sep 16 '25 13:09

Saddam Hussain I H


1 Answers

You can set the graphic to a Label which is rotated, and set the text to an empty string.

private void makeColumnHeader(TableColumn<?,?> column) {
    Label label = new Label();
    label.setText(column.getText());
    column.setText("");
    label.setRotate(90);
    column.setGraphic(label);
}

Here's a complete example:

import javafx.application.Application;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.fxml.FXMLLoader;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

import java.io.IOException;

public class HelloApplication extends Application {

    private void makeColumnHeader(TableColumn<?,?> column) {
        Label label = new Label();
        label.setText(column.getText());
        column.setText("");
        label.setRotate(90);
        column.setGraphic(label);
    }

    @Override
    public void start(Stage stage) throws IOException {
        TableView<Item> table = new TableView<>();
        TableColumn<Item, Number> idColumn = new TableColumn<>("Id");
        idColumn.setCellValueFactory(data -> new SimpleIntegerProperty(data.getValue().id()));
        TableColumn<Item, String> itemColumn = new TableColumn<>("Item");
        itemColumn.setCellValueFactory(data -> new SimpleStringProperty(data.getValue().name()));

        makeColumnHeader(idColumn);
        makeColumnHeader(itemColumn);

        table.getColumns().add(idColumn);
        table.getColumns().add(itemColumn);

        for (int i = 1 ; i <= 20; i++) table.getItems().add(new Item(i, "Item "+i));

        BorderPane root = new BorderPane(table);
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }

    public static record Item(int id, String name){}

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

enter image description here

Note that setting the column's text to an empty string can have undesirable side effects. For example, the tableMenuButton relies on the text in the table columns to display the menu items. Add table.setTableMenuButtonVisible(true); to the code above to see the problem.

A slightly more robust solution is to bind the text of the label in the graphic to the text in the column, and then use CSS to hide the default text:

private void makeColumnHeader(TableColumn<?,?> column) {
    Label label = new Label();
    label.textProperty().bind(column.textProperty());
    label.setRotate(90);
    column.setGraphic(label);
}

and in an external style sheet:

.table-column > .label {
    -fx-content-display: graphic-only;
}
like image 200
James_D Avatar answered Sep 19 '25 05:09

James_D