首页 文章

JavaFX自定义列表单元格,updateItem被调用很多

提问于
浏览
6

我在JavaFX应用程序中使用 ListView . 列表中的项目需要的不仅仅是一个字符串来显示它们,所以我创建了 ListCell<T> 的自定义实现,其中 T 是我正在显示的对象的类 . 在这个自定义类中,我在构造函数中创建 BorderPane 并覆盖 updateItem(T item, boolean empty) . 这个想法是,当调用 updateItem 时,我将单元格的图形设置为BorderPane,同时更改其中的 Label 的一些属性 . 但是,我注意到 updateItem 未被调用一次(例如,当通过滚动回收单元格或添加新项目时),但它被称为 all the time ,例如,当焦点从一个单元格变为另一个单元格时(即使没有滚动),或者调整场景大小,或者按下边框内的按钮时,......

我需要 ListView 自定义 ListCell . 我想在重用单元格时接收 one 回调,传递新项目作为参数呈现 . 然后我想使用该项作为模型来构造一个视图 - 控制器对,我将其视图并将其用作单元格的 graphic . 此视图中的按钮和其他控件应该可以工作 . 这在JavaFX中是否可行?

链接问题:

2 回答

  • 9

    基本思想是很少构造单元格,但可能经常调用 updateItem(...) 方法 . 没有实际保证该项目在 updateItem(...) 的调用之间确实发生了变化 . updateItem(...) 的默认实现负责处理选择,焦点等,因此如果任何属性发生更改(即使项目未更改),则可能需要调用此方法 .

    因此,您应该努力减少 updateItem(...) 方法的开销 . 它'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'与你在进行任何更新之前已经拥有的那个完全不同) .

    我认为 updateItem(...) 确实有些错误名称:它不仅在更新_1370755时被调用,而且在任何时候都需要更新单元格 . 已经存在一种仅在 item 更改时执行代码的机制:只需使用单元格的 itemProperty() 注册一个侦听器 . 您可以使用此技术(我通常更喜欢)创建不同的 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 ;
    });
    

    在您的方案中,此方法可能会更好 .

  • 0

    我能够解释它工作原理的所有细节(它在新项目和现有项目上调用方法),但我解决问题的方法是简单地调用 myContainer.getChildren().removeAll( ... )

    在我实现的ListCell public class MyCell extends ListCell<MyContent> I 'm creating many different items and adding them to a container, which becomes a line in my list view. So, I just had to remove the same items from that container right before I add them back in. Here'的简化版本中我提出了什么建议,但它对我不起作用并产生了相同的错误 .

    @Override
        public void updateItem(MyContent item, boolean empty) {
    
            super.updateItem(item, empty);
    
            if (item == null || empty == true) {
                setGraphic(null);
                setText(null);
            } else {    
    
                // here I user the "item" to decide how to create 
                // objects a, b, c ... which are Rectangle, Label and Label
                // I also update myMainContainer, which is a Pane
    
                myMainContainer.getChildren().removeAll(a, b, c);
                myMainContainer.getChildren().addAll(a, b, c);
                setGraphic(myMainContainer);
            }
        }
    

相关问题