具有自定义对象的JavaFX自定义单元工厂
我正在尝试使用基于自定义objects
列表的自定义Cell
ListView
自定义ListView
。
自定义对象是名为Message
类名,它包含消息内容 , 收件人 , 时间戳和状态 (读取,发送等)的几个字段。
看了这个问题: 使用FXML在JavaFX中自定义ListView我已经成功:
- 创建了一个带有自定义单元格的ListView,其中单元格设计在FXML文件中定义;
- 关联控制器,以便每个单元格数据可以用集合的当前项填充;
但是,我无法链接两者:我似乎无法找到一种方法,以便ListView的当前项被发送到Cell Controller 。
这是我的单元工厂代码和ListView项目填充:
final ObservableList observableList = FXCollections.observableArrayList(); observableList.setAll(myMessages); //assume myMessage is a ArrayList conversation.setItems(observableList); //the listview conversation.setCellFactory(new Callback<ListView, ListCell>() { @Override public ConversationCell call(ListView listView) { return new ConversationCell(); } });
而现在,ConversationCell类:
public final class ConversationCell extends ListCell { @Override protected void updateItem(Message item, boolean empty) { super.updateItem(item, empty); ConversationCellController ccc = new ConversationCellController(null); setGraphic(ccc.getView()); } }
我无法显示ConversationCellController,但我可以说,这是(在其构造函数中)我加载设计单元格的FXML文件,然后我可以用给定的Message项填充值。
getView()
方法返回包含现在填充和设计的单元格的根窗格 。
正如我之前所说,设计工作,但我似乎无法将ListView项目与CellFactory链接,因为在方法中
protected void updateItem(消息项,布尔值为空)
empty设置为true ,item确实为null 。
我能做些什么来完成这项工作?
覆盖updateItem(...)
所有自定义单元实现都需要处理该方法中单元格为空的情况。 所以你可以做一个天真的解决方案
public final class ConversationCell extends ListCell { @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(...)
时updateItem(...)
加载FXML,这是一项相当昂贵的操作(可能涉及文件i / o,从jar文件中解压缩FXML文件,解析文件,批次reflection,创建新的UI元素等)。 每当用户将列表视图滚动几个像素时,您不希望要求FX应用程序线程执行所有工作。 相反,您的单元应缓存节点,并应在updateItem
方法中更新它:
public final class ConversationCell extends ListCell { 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(...)
方法,该方法相应地更新视图(在标签上设置文本等)。