Таблица JavaFX 2.0 с многострочным заголовком таблицы

Можно ли сделать таблицу javaFX 2.0 с многострочным заголовком? Во всех примерах, которые я нашел в Интернете, есть таблицы, где ширина заголовка столбца = его размеру текста, без переноса. Пример того, что у меня есть и что мне нужно, отображается на экране: введите здесь описание изображения


person Victoria Agafonova    schedule 08.06.2012    source источник


Ответы (4)


Я придумал следующую функцию:

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

Полный пример исполняемого файла — в этой сути (требуется файл минимум версия 2.2 для разработчиков).

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

Вероятно, есть лучший способ сделать это, но описанная выше функция, по крайней мере, сработала для меня в моем тестовом примере.

Я думал, что это будет достижимо с помощью простого стиля css, но я не мог заставить его работать только с помощью css.

person jewelsea    schedule 08.06.2012
comment
Во-первых, драгоценности... Я всегда дорожу твоими ответами. Я заметил некоторое странное поведение в Java 8 с этим решением. Первоначально все выглядит нормально, но если я дважды щелкну разделители заголовков столбцов (которые обычно изменяют размер столбца, чтобы он соответствовал содержимому), он продолжает увеличивать ширину столбца. Он никогда не становится меньше, только больше. Любые предложения или идеи относительно того, почему это может происходить? - person Tommo; 11.08.2015
comment
Суть не компилируется. - person Adam Arold; 30.01.2018
comment
У меня компилируется и работает нормально на JavaFX 9.0.4, но все еще страдает от проблемы, на которую указал Томмо. - person jewelsea; 30.01.2018
comment
Я встроил суть, чтобы она не сохранялась на другом сайте, и добавил вызов col.setText(null), который устраняет некоторые проблемы с изменением размера, указанные Томмо (до такой степени, что поведение, по крайней мере, для тестового случая здесь, мне показался приемлемым). В целом, на мой взгляд, использование привязки для макета, как здесь, обычно не является идеальным решением, но лучшего решения у меня пока нет. - person jewelsea; 31.01.2018

Нашел решение без использования ярлыков. В Scene Builder 8.3.0 (Gluon), JavaFX 8 при наведении курсора мыши справа от поля Text появляется кнопка, где в меню можно выбрать многострочный текст.

Меню многострочного режима

В результате получается следующий XML-код:

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

Проще с меткой в ​​заголовке графического столбца:

  1. Добавьте метку в заголовок столбца (если в заголовке столбца есть текст, удалите его).
  2. Установите метку, чтобы разрешить перенос текста (Scene Builder -> перейдите в «Свойства метки» и выберите «Обтекание текстом» или в «Код» -> label.setWrapText (true))
  3. Установите желаемую ширину и высоту этикетки

Примечание: это проще сделать в FXML (с конструктором сцен), чем в коде.

Пример ниже:

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

Пример использования FXML (код не требуется :)):

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

введите здесь описание изображения

person Harry244    schedule 04.06.2015
comment
Есть ли шанс, что вы можете включить код, который привел к столбцу игрока с идентификатором и именем ниже? - person Tommo; 13.06.2015
comment
Вы имеете в виду, как добавить эти два столбца ниже одного основного столбца? если да, код прост: tableColumnPlayer.getColumns().add(tableColumnID); tableColumnPlayer.getColumns().add(tableColumnName); - person Harry244; 17.06.2015

Самый простой способ выровнять текст заголовка — использовать стиль CSS, например:

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

Используйте новую управляющую последовательность строк "\n" в текстовой строке заголовка, чтобы разделить ее на несколько строк.

person user645859    schedule 06.10.2014