Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

TableView

ListView показывает одну строку на элемент. Когда у заметки несколько полей, нагляднее таблица TableView: каждый элемент — строка, каждое поле — колонка. Таблица работает с тем же ObservableList, поэтому почти весь код из прошлого урока остаётся: меняем ListView на TableView и описываем колонки.

Таблица вместо списка

// src/main/java/com/example/notes/App.java — поля класса
private final ObservableList<Note> notes = FXCollections.observableArrayList();
private final TableView<Note> table = new TableView<>(notes);

Фабрика ячеек ListCell больше не нужна. Везде, где было listView, теперь table: модель выбора у таблицы такая же — table.getSelectionModel().

Колонки

Колонка TableColumn имеет два параметра типа: тип строки (Note) и тип значения в ячейке (String). Конструктор принимает текст заголовка, а фабрика значений говорит, что показать в ячейке:

// src/main/java/com/example/notes/App.java — фрагмент start()
TableColumn<Note, String> titleColumn = new TableColumn<>("Заголовок");
titleColumn.setCellValueFactory(cell -> new SimpleStringProperty(cell.getValue().title()));
 
TableColumn<Note, String> categoryColumn = new TableColumn<>("Категория");
categoryColumn.setCellValueFactory(cell -> new SimpleStringProperty(cell.getValue().category()));
 
TableColumn<Note, String> importantColumn = new TableColumn<>("Важная");
importantColumn.setCellValueFactory(
        cell -> new SimpleStringProperty(cell.getValue().important() ? "★" : ""));
 
table.getColumns().add(titleColumn);
table.getColumns().add(categoryColumn);
table.getColumns().add(importantColumn);

cell.getValue() — заметка этой строки. Фабрика должна вернуть свойство, поэтому строку оборачивают в SimpleStringProperty.

Ширина и пустая таблица

// src/main/java/com/example/notes/App.java — фрагмент start()
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY_FLEX_LAST_COLUMN);
table.setPlaceholder(new Label("Заметок пока нет"));
ПолитикаЧто делает
UNCONSTRAINED_RESIZE_POLICYПо умолчанию: колонки своей ширины, справа может остаться пустое место
CONSTRAINED_RESIZE_POLICY_FLEX_LAST_COLUMNКолонки заполняют всю ширину, остаток получает последняя
CONSTRAINED_RESIZE_POLICY_ALL_COLUMNSОстаток делится между всеми колонками

setPlaceholder задаёт надпись, которую таблица покажет, когда в ней нет строк.

Размер окна

Таблице нужно больше места, чем списку. Расширим левую панель и окно:

// src/main/java/com/example/notes/App.java — фрагмент start()
VBox listPane = new VBox(8, table, countLabel);
listPane.setPrefWidth(320);
VBox.setVgrow(table, Priority.ALWAYS);
 
// ...
 
stage.setScene(new Scene(root, 800, 480));

Проверка

Запустите приложение. Слева — таблица с колонками «Заголовок», «Категория» и «Важная»: в первой строке «Купить молоко», «Дом» и звёздочка, во второй «Позвонить Олегу» и «Работа». Справа, как и раньше, форма. Добавьте «Прочитать книгу» с категорией «Идеи» — появится третья строка. Щелчок по заголовку колонки сортирует таблицу по ней, повторный — в обратном порядке, третий — отменяет сортировку.

Частая ошибка

В старых примерах колонку заполняют так: new PropertyValueFactory<>("title"). Этот класс ищет метод getTitle(), а у записи метод называется title(). Колонка остаётся пустой, а в терминале появляется WARNING: Can not retrieve property 'title' in PropertyValueFactory и java.lang.IllegalStateException: Cannot read from unreadable property title. Для записей используйте лямбду, как в этом уроке.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.