JavaFX在控件中显示属性

时间:2018-02-28 02:49:13

标签: java javafx javafx-8

我正在自己完成Oracle的JavaFX教程。经过多年的摇摆(很久以前),我对新的智能功能很着迷,包括。属性。我惊讶地发现这些例子(例如:https://docs.oracle.com/javafx/2/ui_controls/table-view.htm)并没有以我认为“适当”的方式使用它们。

该示例创建一个select t1.id, t1.item, t2.item from t1 left join t2 on t1.id = t2.id and t1.item = t2.item; 类,其属性为字段:

Person

但是吸气剂不适用于属性,而是适用于它们的值

public static class Person {
    private final SimpleStringProperty firstName;
    ...

所以当它将列中的 public String getFirstName() { return firstName.get(); } 绑定到列时,它会将它们包装在一个新属性中:

TableCell

这对我来说似乎很复杂,并且错过了事件传播的真正优势,不仅仅是使用它:

    emailCol.setCellValueFactory(
            new PropertyValueFactory<Person, String>("firstName"));

我的问题:这个例子是否有理由不直接暴露和在控件中使用 bean的属性?我在这里错过了什么吗?

注意:我确实以这种方式更改了代码,示例运行得更好:其他控件在 firstNameCol.setCellValueFactory( celldata -> celldata.getValue().firstNameProperty()); 实体中的更新立即传播,没有调用Person,例如

1 个答案:

答案 0 :(得分:7)

首先,请注意,如果您遵循expected pattern

public class Person {

    private final StringProperty firstName = new SimpleStringProperty();

    public StringProperty firstNameProperty() {
        return firstName ;
    }

    public final String getFirstName() {
        return firstNameProperty().get();
    }

    public final void setFirstName(String firstName) {
        firstNameProperty().set(firstName);
    }
}

然后,无论是table.refresh(),都可以使用任何版本的代码。这是PropertyValueFactory的预期用途,documentation已经相当清楚了。

你是正确的,lambda表达式比PropertyValueFactory更好。除了引用的原因之外,在PropertyValueFactory上使用lambda表达式还有其他主要优点。首先,最重要的是,PropertyValueFactory只是将属性的名称作为String,这意味着它没有编译时检查。所以,如果你拼错了房产的名称:

firstNameCol.setCellValueFactory(new PropertyValueFactory<>("firstname"));

这会编译得很好,你最终会在列中找到空白单元格。这可能很难调试(正如本网站上的问题数量所证明的那样,需要帮助解决这类错误:例如Javafx PropertyValueFactory not populating Tableview)。

其次,PropertyValueFactory通过反射工作,这比lambda表达式慢得多。这可能会导致可测量的性能差异,例如在对包含大量数据的表进行排序时。

引入PropertyValueFactory的原因基本上是历史性的。在Java 8之前,当然没有lambda表达式,所以没有这个便利类的单元工厂的最小实现是通过匿名内部类:

firstNameCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Person, String>, ObservableValue<String>>() {
    @Override
    public ObservableValue<String> call(TableColumn.CellDataFeatures<Person, String> cellData) {
        return cellData.getValue().firstNameProperty();
    }
});

由于该代码非常可怕,JavaFX团队引入PropertyValueFactory只是为了使API更易于使用。

使用Java 8及更高版本时,PropertyValueFactory应该被视为遗留类,而lambda表达式应该是首选。当然,早于Java 8的文档仍然存在(实际上,您明确地链接了JavaFX 2中的文档 - 虽然most recent version仍然没有更新),并且 - 坦率地说 - 也是许多其他作家在没有正确思考的情况下复制这种风格。完全弃用PropertyValueFactory类可能有一个很好的例子。

(所以:TL; DR:不,你没有遗漏任何东西。)