【问题标题】:How to specify what property a JavaFX ListView should display when using a custom object?使用自定义对象时,如何指定 JavaFX ListView 应显示的属性?
【发布时间】:2017-11-19 17:50:05
【问题描述】:

我在我的 FXML 文件中定义了一个 ListView 来保存 MyCustomData 对象。我能弄清楚如何告诉它要显示 MyCustomData 的哪个属性的唯一方法是将以下代码添加到我的控制器:

myList.setCellFactory(new Callback<ListView<MyCustomData>, ListCell<MyCustomData>>() {
    @Override
    public ListCell<MyCustomData> call(ListView<MyCustomData> param) {
        return new ListCell<MyCustomData>() {
            @Override
            protected void updateItem(MyCustomData item, boolean empty) {
                super.updateItem(item, empty);
                if(item != null) {
                    setText(item.getMyProperty());
                }
            }
        };
    }
});

用 FXML 中的一行代码替换所有这些杂乱的代码肯定会很好,该代码指定应显示的属性。这可能吗?

【问题讨论】:

    标签: listview user-interface javafx


    【解决方案1】:

    首先请注意,您的单元实现存在错误。您必须处理updateItem(...) 方法中的所有可能性。在您的实现中,如果单元格当前显示一个项目,然后作为一个空单元格重复使用(例如,如果项目被删除),则该单元格将不会清除其文本。

    如果将Callback 实现为 lambda 表达式,而不是匿名内部类,则可以显着减少代码量:

    myList.setCellFactory(lv -> new ListCell<MyCustomData>() {
        @Override
        protected void updateItem(MyCustomData item, boolean empty) {
            super.updateItem(item, empty);
            setText(item == null ? null : item.getMyProperty() );
        }
    });
    

    如果你做了很多这样的事情,并且想进一步减少代码量,那么创建一个通用的可重用单元工厂实现并不难:

    public class ListViewPropertyCellFactory<T> 
        implements Callback<ListView<T>, ListCell<T>> {
    
        private final Function<T, String> property ;
    
        public ListViewPropertyCellFactory(Function<T, String> property) {
            this.property = property ;
        }
    
        @Override
        public ListCell<T> call(ListView<T> listView) {
            return new ListCell<T>() {
                @Override
                protected void updateItem(T item, boolean empty) {
                    super.updateItem(item, boolean);
                    setText(item == null ? null : property.apply(item));
                }
            };
        }
    }
    

    你可以使用的

    myList.setCellFactory(new ListViewPropertyCellFactory<>(MyCustomData::getMyProperty));
    

    如果您更喜欢功能性更强的风格而不是创建实现 Callback 的类,您可以类似地这样做

    public class ListViewPropertyCellFactory {
    
        public static <T> Callback<ListView<T>, ListCell<T>> of(Function<T, String> property) {
            return lv -> new ListCell<T>() {
                @Override
                protected void updateItem(T item, boolean empty) {
                    super.updateItem(item, boolean) ;
                    setText(item == null ? null : property.apply(item));
                }
            };
        }
    }
    

    myList.setCellFactory(ListViewPropertyCellFactory.of(MyCustomData::getMyProperty));
    

    【讨论】:

      猜你喜欢
      • 2017-05-04
      • 2016-08-08
      • 2018-06-20
      • 2016-08-23
      • 1970-01-01
      • 2020-10-27
      • 1970-01-01
      相关资源
      最近更新 更多