導入
JavaFXで一覧を表示する定番の部品がListViewです。ただしListViewが直接扱えるのはObservableListという、要素の増減を自動で検知できる特別なリストで、第6章のTaskListViewModel.getTasks()が返す普通のList<TaskDto>とは型が違います。この差をどこで埋めるかが、この回の主題です。
説明
flowchart LR
VM["TaskListViewModel<br/>getTasks(): List<TaskDto>"] -->|"Controllerがコピーする"| OL["ObservableList<TaskDto><br/>(Controllerが保持)"]
OL -->|"表示"| LV["ListView(View)"]
OL -.変更通知.-> LV
private final ObservableList<TaskDto> items = FXCollections.observableArrayList();
private void refresh() {
// ViewModelの List を、View専用の ObservableList へ詰め替える
items.setAll(viewModel.getTasks());
taskListView.setItems(items);
}
viewModel.getTasks()は**普通のList<TaskDto>**を返すだけでよい。ObservableListを知る必要は無い(レッスン2の「ViewModelはJavaFXの画面部品を一切知らない」という原則そのもの)ObservableListへの詰め替えはController側の仕事。items.setAll(...)は中身を丸ごと入れ替え、ListViewはその変更を検知して自動的に再描画する- 一覧の各行の見た目(タイトルだけを表示するか、優先度も並べるか)は
setCellFactoryで自由に組み立てられる
taskListView.setCellFactory(list -> new ListCell<>() {
@Override
protected void updateItem(TaskDto task, boolean empty) {
super.updateItem(task, empty);
setText(empty || task == null ? null : "[" + task.priorityLabel() + "] " + task.title());
}
});
TaskDtoが第6章のrecordだったおかげで、task.title()・task.priorityLabel()のようにアクセサがそのまま使えます。
まとめ
- ViewModelは
List<TaskDto>という普通のコレクションだけを返せばよく、ObservableListへの詰め替えはController(View側)の仕事 ObservableListは要素の増減を自動で検知し、ListViewを再描画させる- 表示の見た目(1行をどう組み立てるか)は
setCellFactoryで自由に決められる
次回: 実際に手を動かして、入力とタスクの追加をViewModel側から固めます。