カスタムListView
のリストに基づいて、カスタムCell
で作られたカスタムobjects
を作成しようとしています。
カスタムオブジェクトはMessage
というクラス名で、メッセージのいくつかのフィールドが含まれていますcontent、受信者、timestampおよびstatus (読み取り、送信など)。
この質問を見た後: FXMLを使用してJavaFXでListViewをカスタマイズ 私は無事に成功しました:
ただし、両方をリンクできませんでした。ListViewの現在のアイテムにCell Controllerが送信されるようにする方法が見つからないようです。
これがセルファクトリーとリストビューの項目の充填の私のコードです。
_final ObservableList observableList = FXCollections.observableArrayList();
observableList.setAll(myMessages); //assume myMessage is a ArrayList<Message>
conversation.setItems(observableList); //the listview
conversation.setCellFactory(new Callback<ListView<Message>, ListCell<Message>>() {
@Override
public ConversationCell<Message> call(ListView<Message> listView) {
return new ConversationCell();
}
});
_
そして今、ConversationCellクラス:
_public final class ConversationCell<Message> extends ListCell<Message> {
@Override
protected void updateItem(Message item, boolean empty) {
super.updateItem(item, empty);
ConversationCellController ccc = new ConversationCellController(null);
setGraphic(ccc.getView());
}
}
_
ConversationCellControllerを表示することはできませんが、言えることは、これが(そのコンストラクターで)セルを設計するFXMLファイルをロードし、指定されたメッセージアイテムで値を入力できる場所です。
getView()
メソッドは、現在塗りつぶされてデザインされたセルを含むルートペインを返します。
前に言ったように、設計は機能しますが、リストビューアイテムをCellFactoryにリンクできないようです。
protected void updateItem(Message item、boolean empty)
emptyはtrueに設定され、アイテムは確かにnull。
これを機能させるにはどうすればよいですか?
updateItem(...)
をオーバーライドするすべてのカスタムセル実装は、そのメソッドでセルが空の場合に対処する必要があります。だからあなたはこれの素朴な修正を行うことができます
_public final class ConversationCell<Message> extends ListCell<Message> {
@Override
protected void updateItem(Message item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
} else {
// did you mean to pass null here, or item??
ConversationCellController ccc = new ConversationCellController(null);
setGraphic(ccc.getView());
}
}
}
_
ただし、これはパフォーマンスの観点からは良い解決策ではありません。空でないセルを使用してupdateItem(...)
が呼び出されるたびにFXMLをロードしていますが、これはかなりコストのかかる操作です(ファイルI/Oが含まれる可能性があり、jarファイルからFXMLファイルを解凍し、ファイルを解析します)。多くのリフレクション、新しいUI要素の作成など)。ユーザーが数ピクセルずつリストビューをスクロールするたびに、FXアプリケーションスレッドがすべての作業を実行するように要求するのは望ましくありません。代わりに、セルはノードをキャッシュし、updateItem
メソッドで更新する必要があります。
_public final class ConversationCell<Message> extends ListCell<Message> {
private final ConversationCellController ccc = new ConversationCellController(null);
private final Node view = ccc.getView();
@Override
protected void updateItem(Message item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
} else {
ccc.setItem(item);
setGraphic(view);
}
}
}
_
ビューを更新する(ラベルにテキストを設定するなど)_ConversationCellController
のsetItem(...)
メソッドを定義する必要があります。