我在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中的单行代码替换所有这些混乱的代码肯定会很好,它指定了应该显示的属性。这可能吗?
答案 0 :(得分: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));