JavaFX 2.0 Table with multiline table header

匿名 (未验证) 提交于 2019-12-03 08:46:08

问题:

Is it possible to make javaFX 2.0 table with multiline header? All the examples, which i have found on the web, have tables, where columnt header width = its text size, without wraping. The exaple of what i have, and what i need is shown on a screen:

回答1:

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); } 

A complete executable example is in this gist (requires the 2.2 developer preview as a minimum).

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); }   } } 

There is probably a better way to do this, but the function above did at least work for me in my test case.

I thought this would be achievable with a simple css style, but I could not get it to work via css alone.



回答2:

Is easier with a Label in the header graphic of the column:

  1. Add a label in the column header graphic (if the column has some text as title delete it).
  2. Set the label to allow Wrap Text (Scene Builder -> go to Properties of the label and select Wrap Text or in Code -> label.setWrapText(true))
  3. Set label width and height we wish

Note: is easier to do this in a FXML (with 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 using FXML (No code needed :) ):

<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> 



回答3:

Found a solution without using labels. In Scene Builder 8.3.0 (Gluon) , JavaFX 8 , a button appears on mouse hover, just right of the Text field, where a multi - line can be chosen from the menu.

This results in a following XML code:

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


回答4:

The easiest way to align header text is with CSS style, like this:

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

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



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!