JavaFX自定义列表单元格,updateItem被调用很多 [英] JavaFX custom list cell, updateItem being called a lot

查看:639
本文介绍了JavaFX自定义列表单元格,updateItem被调用很多的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在JavaFX应用程序中使用 ListView 。列表中的项目需要的不仅仅是一个字符串来显示它们,所以我做了一个 ListCell< T> 的自定义实现,其中 T 是我正在显示的对象的类。在这个自定义类中,我在构造函数中创建了一个 BorderPane 并覆盖 updateItem(T item,boolean empty)。我的想法是,当调用 updateItem 时,我将单元格的图形设置为BorderPane,同时更改 Label 里面的。但是,我注意到 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 Labels 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 ListCells. 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?

链接问题:

  • 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆