本文へスキップ
BecomeCoder

Java MVVMコース · 第7章 View ― JavaFXへ接続する · レッスン27

一覧表示 ― ListViewとObservableList

ローカル実施

導入

JavaFXで一覧を表示する定番の部品がListViewです。ただしListViewが直接扱えるのはObservableListという、要素の増減を自動で検知できる特別なリストで、第6章TaskListViewModel.getTasks()が返す普通のList<TaskDto>とは型が違います。この差をどこで埋めるかが、この回の主題です。

説明

flowchart LR
    VM["TaskListViewModel<br/>getTasks(): List&lt;TaskDto&gt;"] -->|"Controllerがコピーする"| OL["ObservableList&lt;TaskDto&gt;<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側から固めます。