JavaFX 2.0 table with multi-row table header

Is it possible to create a javaFX 2.0 table with a multi-line header? All the examples I found on the Internet have tables in which the column heading width = its text size, without crashing. The exam of what I have and what I need is displayed on the screen: enter image description here

+6
source share
4 answers

I came up with the following function:

private void makeHeaderWrappable(TableColumn col) { Label label = new Label(col.getText()); label.setStyle("-fx-padding: 8px;"); label.setWrapText(true); label.setAlignment(Pos.CENTER); label.setTextAlignment(TextAlignment.CENTER); StackPane stack = new StackPane(); stack.getChildren().add(label); stack.prefWidthProperty().bind(col.widthProperty().subtract(5)); label.prefWidthProperty().bind(stack.prefWidthProperty()); col.setGraphic(stack); } 

Full executable example in this value ( 2.2 developer preview required at least ).

 import javafx.application.Application; import javafx.beans.property.SimpleStringProperty; import javafx.collections.FXCollections; import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.layout.Pane; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import javafx.scene.text.TextAlignment; import javafx.stage.Stage; public class TableWrappedHeaders extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) { TableColumn firstNameCol = new TableColumn("First Name (which is a really long name)"); makeHeaderWrappable(firstNameCol); firstNameCol.setPrefWidth(100); firstNameCol.setCellValueFactory(new PropertyValueFactory<Person,String>("firstName")); TableColumn lastNameCol = new TableColumn("Last Name"); lastNameCol.setPrefWidth(100); lastNameCol.setCellValueFactory(new PropertyValueFactory<Person,String>("lastName")); TableView table = new TableView(); table.getColumns().addAll(firstNameCol, lastNameCol); table.setItems(FXCollections.observableArrayList( new Person("Jacob", "Smith"), new Person("Isabella", "Johnson"), new Person("Ethan", "Williams") )); table.setPrefSize(250, 200); Pane layout = new VBox(10); layout.setStyle("-fx-padding: 10;"); layout.getChildren().addAll(table); stage.setScene(new Scene(layout)); stage.show(); } private void makeHeaderWrappable(TableColumn col) { Label label = new Label(col.getText()); label.setStyle("-fx-padding: 8px;"); label.setWrapText(true); label.setAlignment(Pos.CENTER); label.setTextAlignment(TextAlignment.CENTER); StackPane stack = new StackPane(); stack.getChildren().add(label); stack.prefWidthProperty().bind(col.widthProperty().subtract(5)); label.prefWidthProperty().bind(stack.prefWidthProperty()); col.setText(null); col.setGraphic(stack); } public static class Person { private final SimpleStringProperty firstName; private final SimpleStringProperty lastName; private Person(String fName, String lName) { this.firstName = new SimpleStringProperty(fName); this.lastName = new SimpleStringProperty(lName); } public String getFirstName() { return firstName.get(); } public void setFirstName(String fName) { firstName.set(fName); } public String getLastName() { return lastName.get(); } public void setLastName(String fName) { lastName.set(fName); } } } 

Perhaps the best way to do this, but the above function at least worked for me in my test case.

I thought this would be achievable with a simple CSS style, but I couldn't get it to work only with CSS.

+7
source

With a label in the column heading of a column is easier:

  • Add a label in the column heading graph (if the column contains text as a heading, delete it).
  • Set a shortcut to allow text to flow around (Scene Builder → go to Label Properties and select Wrap Text or in Code → label.setWrapText (true))
  • Set the width and height of the label.

Note. This is easier to do in FXML (using Scene Builder) than in code.

Example below:

  public class TableColumnLongTextLabel extends Application { @Override public void start(Stage stage) { TableView table = new TableView(); TableColumn tableColumnData1 = new TableColumn(), tableColumnData2 = new TableColumn("Long Title without Text Wrap"); tableColumnData1.setCellValueFactory(new PropertyValueFactory<SomeStructure, String>("data1")); tableColumnData2.setCellValueFactory(new PropertyValueFactory<SomeStructure, String>("data2")); table.getColumns().addAll(tableColumnData1, tableColumnData2); Label columnTitle = new Label("Long Title with Text Wrapped"); columnTitle.setPrefWidth(125); columnTitle.setPrefHeight(50); columnTitle.setWrapText(true); columnTitle.setTextAlignment(TextAlignment.CENTER); tableColumnData1.setGraphic(columnTitle); table.setItems(FXCollections.observableArrayList( new SomeStructure("Java", "FX", 1), new SomeStructure("Java", "Swing", 0), new SomeStructure("Java", "Sample", 2), new SomeStructure("Some", "Other", 10) )); Pane layout = new VBox(10); layout.getChildren().addAll(table); stage.setScene(new Scene(layout, 350, 350)); stage.show(); } public static class SomeStructure { private final SimpleStringProperty data1; private final SimpleStringProperty data2; private final SimpleIntegerProperty data3; private SomeStructure(String data1, String data2, Integer data3) { this.data1 = new SimpleStringProperty(data1); this.data2 = new SimpleStringProperty(data2); this.data3 = new SimpleIntegerProperty(data3); } public String getData1() { return data1.get(); } public void setData1(String data1) { this.data1.set(data1); } public String getData2() { return data2.get(); } public void setData2(String data2) { this.data2.set(data2); } public Integer getData3() { return data3.get(); } public void setData3(Integer data3) { this.data3.set(data3); } } public static void main(String[] args) { launch(args); } } 

Example of using FXML (no code required :)):

 <TableView prefHeight="251.0" prefWidth="556.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"> <columns> <TableColumn editable="false" maxWidth="90.0" prefWidth="70.0" sortable="false" text="Player"> <columns> <TableColumn editable="false" maxWidth="80.0" prefWidth="50.0" text="ID" /> <TableColumn editable="false" maxWidth="200.0" prefWidth="180.0" text="Name" /> </columns> </TableColumn> <TableColumn maxWidth="80.0" minWidth="50.0" prefWidth="60.0" text="Game" /> <TableColumn editable="false" maxWidth="160.0" minWidth="125.0" prefWidth="135.0" sortable="false" text="Team" visible="false" /> <TableColumn editable="false" maxWidth="160.0" minWidth="107.0" prefWidth="107.0" sortable="false"> <graphic> <Label alignment="CENTER" text="Individual Points (Big Team)" textAlignment="CENTER" wrapText="true" /> </graphic> </TableColumn> <TableColumn editable="false" maxWidth="160.0" minWidth="99.0" prefWidth="102.0" sortable="false"> <graphic> <Label alignment="CENTER" text="Team Points (Small Maps)" textAlignment="CENTER" wrapText="true" /> </graphic> </TableColumn> <TableColumn editable="false" maxWidth="116.0" minWidth="55.0" prefWidth="55.0" sortable="false"> <graphic> <Label text="Total Points" textAlignment="CENTER" wrapText="true" /> </graphic> </TableColumn> </columns> </TableView> 

enter image description here

+6
source

Found a solution without using tags. In Scene Builder 8.3.0 (Gluon), JavaFX 8, the button appears when you hover, right to the right of the Text field, where a multi-line line can be selected in the menu.

Menu for multi-line mode

This results in the following XML code:

 <TableColumn fx:id="prodDisc" editable="false" prefWidth="50.0" text="Prod &#10;Disc" /> 
+6
source

The easiest way to align header text is with a CSS style, for example:

 .table-view .column-header .label { -fx-text-alignment: center; } 

Use the new escape line "\ n" in the header text line to split it into multiple lines.

+3
source

Source: https://habr.com/ru/post/917644/


All Articles