Java:setCellValuefactory; Lambda与PropertyValueFactory; 优点缺点

Wol*_*one 4 java javafx

今天我在尝试学习JavaFX和Java的更多内容时遇到了另一件我并不理解的事情.

参考是以下教程(我试图将原理应用于组织者):

JavaFX 8教程

我将简要介绍一下我有问题的特定部分:

我的主窗口包含一个tableview,显示一些约会数据.所以我得到了一些这种风格的线条(与教程中相同):

aColumn.setCellValueFactory(cellData ->cellData.getValue().getAColumnsProperty());
Run Code Online (Sandbox Code Playgroud)

可以通过额外的EditDialog操纵数据.这很好用.如果我编辑的东西,立即显示更改,但我做了一些额外的研究,以更好地了解Lambda(不太成功).现在......在线java文档Java Doc PropertyValueFactory中说:"Callback-Interface的一个便利实现,[...]"

所以我将我的代码重构为这种风格:

aColumn.setCellValueFactory(new PropertyValueFactory<Appointment,LocalDate>("date"));
Run Code Online (Sandbox Code Playgroud)

我发现它比Lambda更具可读性.但我注意到,当我进行更改时,我需要在显示更改之前对TableView进行一些排序.

是否有可能在第二种方法中立即显示变化?

如果是的话:是否存在阻碍这种修改的重大缺陷?也就是Lambda是这种情况下的最佳实践?

我感谢任何帮助.

fab*_*ian 11

PropertyValueFactory期望正确命名的属性getter.getAColumnsProperty可能不是一个.

在的情况下new PropertyValueFactory<Appointment, LocalDate>("date")Appointment类需要包含一个dateProperty()方法; 返回的值需要扩展ReadOnlyProperty才能工作,任何编辑只会导致模型自动更新(如果返回的对象也是如此)WritableValue.

Appointment应该使用的示例类PropertyValueFactory<>("date"):

public class Appointment {
    private final ObjectProperty<LocalDate> date = new SimpleObjectProperty<>();

    public final LocalDate getDate() {
        return this.date.get();
    }

    public final void setDate(LocalDate value) {
        this.date.set(value);
    }

    public final ObjectProperty<LocalDate> dateProperty() {
        return this.date;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果不存在这样的方法,PropertyValueFactory将使用getter来检索值,即getDate(),但是在更新之前,模型中的这种情况更新将不会在UI中可见Cell,因为PropertyValueFactory"不知道"在何处添加侦听器.

缺点 PropertyValueFactory

  • 只能publicpublic类中查找方法
  • PropertyValueFactory 使用反射
  • 不是类型安全的.在new PropertyValueFactory<Appointment, LocalDate>("date")编译器中没有检查,如果有合适的方法,如果该方法甚至返回一个合适的类,或者如果属性getter返回a String而不是a ReadOnlyProperty<LocalDate>可以导致ClassCastExceptions.
  • 没有编译时检查.在lambda表达式中,编译器可以检查方法是否存在并返回适当的类型; 有PropertyValueFactory没有这样做.

如果你一定要实现正确的物品类别相应的方法,有什么错误使用PropertyValueFactory,但如上所述它有它的缺点.而且实施Callback更灵活.你可以做一些额外的修改:

TableColumn<Appointment, String> column = ...

column.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Appointment, String>, ObservableValue<String>> {
    @Override
    public ObservableValue<String> call(TableColumn.CellDataFeatures<Appointment, String> cd) {
        Appointment a  = cd.getValue();

        return Bindings.createStringBinding(() -> "the year: " + a.getDate().getYear(), a.dateProperty());
    }

});
Run Code Online (Sandbox Code Playgroud)