JavaFX の ListView で String 以外を構成要素にするの拡張的な内容になりますが、
ListView の表示が toString() では収まらない、文字列以外も表示したい、という際には、ListView のリストを構成する Cell をカスタマイズすることになります。
その Cell をカスタマイズした一例として…
やりたかったことは ListView にファイル名と対応するアイコンの表示。
ポイントは ListView の Cell のカスタマイズと Icon の描画方法。
といっても、ほとんど
JavaFX file listview with icon and file name - Stack Overflow
http://stackoverflow.com/questions/28034432/javafx-file-listview-with-icon-and-file-name
のマネです。
Item というクラスがファイル名などを持っていて、ListView<Item> として ListView の要素のクラスとなっているとします。
ListView#setCellFactory() で Cell をカスタマイズする ListCell を拡張したクラス(この場合 ItemFormatCell)を返すようにします。
listView.setCellFactory(new Callback<ListView<Item>, ListCell<Item>>() {
@Override
public ListCell<Item> call(ListView<Item> list) {
return new ItemFormatCell();
}
});
ItemFormatCell クラスで、実際に1つのセルの表示内容をカスタマイズすることになりますが、ここで updateItem() をオーバーライドして実装するのが定番のようです。
次の例では、
- 空行には何も表示しない(setText(), setGraphic() で null 指定)
- 対応する Item がある場合には、アイコン(setGraphic())+ファイル名(setText())を表示する
ということをやっています。
final class ItemFormatCell extends ListCell<Item> {
public ItemFormatCell() { }
@Override protected void updateItem(Item item, boolean empty) {
final boolean bUseJLabel = false;
super.updateItem(item, empty);
if(empty || item == null){
setText(null);
setGraphic(null);
return;
}
// getItemName() はファイル名を返すメソッドとして実装
setText(item.getItemName());
setContentDisplay(ContentDisplay.LEFT); // Graphic は Text の左に表示
// getIcon() は対応する Icon を返すメソッドとして実装
// Windows では FileSystemView.getFileSystemView().getSystemIcon() を利用
Icon icon = item.getIcon();
BufferedImage bufferedImage = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
icon.paintIcon(null, bufferedImage.getGraphics(), 0, 0);
// 最終的に Icon を ImageView の形で Cell に表示
setGraphic(new ImageView(SwingFXUtils.toFXImage(bufferedImage, null)));
}
}
ListView の Cell のカスタマイズについては、Cell の javadoc も参照してみて下さい。
※補足
Icon を setGraphic() に渡せるようにする手順ですが、
上記の方法とは別に
- Icon を swing の JLabel で表示させる
- その JLabel を JavaFX の SwingNode に setContent()
- その SwingNode を setGraphic()
という swing の GUI部品を使った方法も試してみて、こちらの方がコード的にはシンプルだったのですが、
動作が少し遅いのと、どうしても JavaFX の Platform.exit() 時にアプリケーションが終わらない(多分、Swing のスレッドが残ってしまっていて、消し方が分からなかった)という理由で没にしました。
0 件のコメント:
コメントを投稿