JavaFX自定义列表单元格,updateItem被调用很多 [英] JavaFX custom list cell, updateItem being called a lot
问题描述
我在JavaFX应用程序中使用 ListView
。列表中的项目需要的不仅仅是一个字符串来显示它们,所以我做了一个 ListCell< T>
的自定义实现,其中 T
是我正在显示的对象的类。在这个自定义类中,我在构造函数中创建了一个 BorderPane
并覆盖 updateItem(T item,boolean empty)
。我的想法是,当调用 updateItem
时,我将单元格的图形设置为BorderPane,同时更改 Label $ c $的某些属性c>里面的。但是,我注意到
updateItem
未被调用一次(例如,当通过滚动回收单元格或添加新项目时),但它始终被称为 ,例如当焦点从一个单元格变为另一个单元格时(即使没有滚动),或者调整场景大小,或者按下borderpane中的按钮时,......
I'm using a ListView
in a JavaFX application. The items in the list require more than just a string to display them so I made a custom implementation of ListCell<T>
, where T
is the class of the objects I'm displaying. In this custom class, I create a BorderPane
in the constructor and override updateItem(T item, boolean empty)
. The idea was that when updateItem
is called, I set the graphic of the cell to be the BorderPane while change some properties of Label
s inside of it. However, I noticed updateItem
is not called once (e.g. when a cell is recycled through scrolling or a new item is added), but it is called all the time, e.g. when the focus changes from one cell to another (even without scrolling), or when the scene is resized, or when a button inside the borderpane is pressed, ...
我需要一个带有自定义 ListCell
的 ListView
。我想在重用单元格时接收一个回调,传递新项目作为参数呈现。然后我想使用该项作为模型来构造一个视图 - 控制器对,我将其视图并将其用作单元格的图形
。此视图中的按钮和其他控件应该可以工作。这可能在JavaFX中吗?
I need to have a ListView
with custom ListCell
s. I want to receive one callback when a cell is reused, passing the new item to be rendered as a parameter. Then I want to use that item as a model to construct a view-controller pair of which I take the view and use it as the graphic
of the cell. Buttons and other controls inside this view should work. Is this possible in JavaFX?
链接问题:
- ListView中的细胞回收 - JavaFX
- 每个单元格中带按钮的javafx listview (我已经完成了这个顺便说一下,按钮回调有效,但仍有太多回调
updateItem
)
- Weird recycle of cells in ListView - JavaFX
- javafx listview with button in each cell (I've done this btw and the button callback works, but there are still way too many callbacks to
updateItem
)
推荐答案
基本思想是很少构造单元格,但可能会调用 updateItem(...)
方法经常。实际上没有保证在调用 updateItem(...)
之间项目确实发生了变化。 updateItem(...)
的默认实现负责处理选择,焦点等,因此如果任何属性发生更改,则可能需要调用此方法(即使该项目未更改。)
The basic idea is that cells are constructed rarely but the updateItem(...)
method is likely to be called frequently. There is no actual guarantee that the item has really changed between calls to updateItem(...)
. The default implementation of updateItem(...)
takes care of handling selection, focus, etc, so this method probably needs to be invoked if any of those properties change (even if the item has not changed).
因此,您应该努力减少 updateItem(...)
方法。目前尚不清楚多次频繁调用是否会阻止您执行所需操作(例如,当您将新项目作为参数传递给模型时,请检查它是否与您在进行任何更新之前已经存在的实际不同) 。
You should therefore strive to reduce the overhead of the updateItem(...)
method. It's not clear that multiple, frequent calls would prevent you doing what you want (for example, when you pass the new item as a parameter to your model, check to see if it's really different to the one you already have before doing any updates).
我认为 updateItem(...)
确实有些错误名称:它不仅被称为项目
已更新,但实际上任何时候都需要更新单元格。已经存在一种仅在项
更改时执行代码的机制:只需使用单元格的 itemProperty()
注册一个侦听器。您可以使用此技术(我通常更喜欢)创建不同的 ListCell
样式:
I'd argue that updateItem(...)
is really somewhat misnamed: it's called not only when the item
is updated, but really any time the cell might need to be updated. There's already a mechanism for executing code only when the item
changes though: just register a listener with the cell's itemProperty()
. You can use this technique (which I generally prefer) to create a different style of ListCell
:
ListView<...> listView = ... ;
listView.setCellFactory(lv -> {
BorderPane cellRoot = new BorderPane();
// create nodes, register listeners on them, populate cellRoot, etc...
ListCell<...> cell = new ListCell<>();
cell.itemProperty().addListener((obs, oldItem, newItem) -> {
if (newItem != null) {
// update cellRoot (or its child nodes' properties) accordingly
}
});
cell.emptyProperty().addListener((obs, wasEmpty, isEmpty) -> {
if (isEmpty) {
cell.setGraphic(null);
} else {
cell.setGraphic(cellRoot);
}
});
cell.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
return cell ;
});
此方法在您的方案中可能会更好。
This approach may work better in your scenario.
这篇关于JavaFX自定义列表单元格,updateItem被调用很多的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!