JavaFX:ListViewの基本的な使い方
JavaFXでListViewやTableViewを使う際には、ObservableList
今回のエントリでは、ListViewについて。次回はTableViewの予定。
ListView
基本的な使い方(文字列のListView)
MWではGenerateConfirm/SelectMementoTypeで使用しているような、単純に文字列を描画するリスト(ListView
import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.scene.control.ListView; public class SelectMementoTypeController extends AnchorPane implements MWSceneController { // 画面項目 @FXML private ListView<String> listView; private ObservableList<String> listRecords = FXCollections.observableArrayList(); /** * ListViewにメメントタイプ一覧を設定する */ private void fillTypeListView(){ for(String category:processor.findMementoCategoryProcess()){ logger.info("カテゴリ["+category+"]を追加します。"); listRecords.add(category); } listView.setItems(listRecords); } }
CellFactoryを用いる方法(カスタムクラスのリスト)
文字列リストとかならとてもシンプルなのだが、内部的に管理するデータはMementoのリストとし、画面上にはMementoのパスをリスト表示したい場合などにはCellFactoryを使用することになるので簡単にメモ。
ちなみに、MWではPublishedMementoListで使用している。
参考としたのは、Ensemble(Java SE Downloads)のList View Cell Factoryと、IT Proさんの記事(Java技術最前線 - JavaFX 2で始めるGUI開発 第5回 リスト、コンボボックス、テーブル:ITpro)。
コード関連箇所の抜粋(PublishedMementoListController)
import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.scene.control.ListCell; import javafx.scene.control.ListView; import javafx.util.Callback; public class PublishedMementoListController extends AnchorPane implements MWSceneController { // 画面項目 @FXML private Label typeLabel; @FXML private ListView<Memento> listView; private ObservableList<Memento> listRecords = FXCollections.observableArrayList(); /** * ListViewにメメント一覧を設定する */ private void fillMementoListView(String category){ for(Memento me:processor.findMementoProcess(category)){ logger.info("メメント["+me+"]を追加します。"); listRecords.add(me); } listView.setItems(listRecords); listView.setCellFactory(new Callback<ListView<Memento>, ListCell<Memento>>() { @Override public ListCell<Memento> call(ListView<Memento> arg0) { return new MementoCell(); } }); } /** * ListView<Memento>表示用のセル * @author kazyury */ private static class MementoCell extends ListCell<Memento> { @Override protected void updateItem(Memento me, boolean empty) { super.updateItem(me, empty); if(!empty) { setText(me.getProductionPath()); } } } }
ListViewとObservableListの定義
内部データの設定については文字列のListViewとほぼ同様。
異なるのは、ListViewとObservableListの型をMementoで定義するのみ。
@FXML private ListView<Memento> listView; private ObservableList<Memento> listRecords = FXCollections.observableArrayList();
ObservableListへのデータ追加とListViewとのバインド
基本型と全く同じ。
for(Memento me:processor.findMementoProcess(category)){ logger.info("メメント["+me+"]を追加します。"); listRecords.add(me); } listView.setItems(listRecords);
ListView用のCellFactory
ListViewにMementoを突っ込んでもListView君は何を描画したらよいか判らないだろうから、Memento用のCellを別途定義する必要がある。
まずは、ListViewにどのCellを使うのかを教える。ここはほぼイディオム的なものなのかな?
listView.setCellFactory(new Callback<ListView<Memento>, ListCell<Memento>>() { @Override public ListCell<Memento> call(ListView<Memento> arg0) { return new MementoCell(); } });
また、Memento用のCellはListCellを継承して別途定義して、そのCellで描画する内容を制御するようにする。Cell内容の描画はCell#updateItem()で行うようなので、そこをOverrideして、setTextする際にメメントの実行時環境でのパスを表示するように修正する。
/** * ListView<Memento>表示用のセル * @author kazyury */ private static class MementoCell extends ListCell<Memento> { @Override protected void updateItem(Memento me, boolean empty) { super.updateItem(me, empty); if(!empty) { setText(me.getProductionPath()); } } }
このような形になる。