JavaFX 在控件中显示属性
JavaFX Displaying properties in controls
我正在学习 Oracle 的 JavaFX 教程。在使用 Swing 多年(很久以前)之后,我对新的智能功能非常着迷,包括。特性。我很惊讶地看到这些示例(例如:https://docs.oracle.com/javafx/2/ui_controls/table-view.htm)没有按照我认为的方式使用它们 "proper"。
该示例创建一个 Person
class,其中属性作为字段:
public static class Person {
private final SimpleStringProperty firstName;
...
但是 getter 不是针对属性,而是针对它们的值
public String getFirstName() {
return firstName.get();
}
所以当它将它们绑定到列中的 TableCell
s 时,它会将它们包装在一个新的 属性 中:
emailCol.setCellValueFactory(
new PropertyValueFactory<Person, String>("firstName"));
这对我来说似乎很复杂,并且错过了事件传播的真正优势,而不是简单地使用它:
firstNameCol.setCellValueFactory( celldata ->
celldata.getValue().firstNameProperty());
我的问题:为什么这个示例不公开并直接在控件中使用 bean 的属性是有原因的吗?我在这里遗漏了什么吗?
注意:我确实以这种方式更改了代码,并且该示例工作得更好:立即传播另一个控件在 Person
实体中的更新,w/o 调用 table.refresh()
例如
首先请注意,如果您遵循 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
更好的方法。除了您引用的原因之外,使用 lambda 表达式比 PropertyValueFactory
还具有其他主要优势。首先,也是最重要的,PropertyValueFactory
只是将 属性 的名称作为 String
,这意味着没有 compile-time 检查它。因此,如果您拼错 属性:
的名称
firstNameCol.setCellValueFactory(new PropertyValueFactory<>("firstname"));
这会编译得很好,你只会在列中得到空白单元格。这可能很难调试(本网站上寻求此类错误帮助的问题数量证明了这一点:例如 Javafx PropertyValueFactory not populating Tableview)。
其次,PropertyValueFactory
通过反射工作,这比 lambda 表达式慢得多。这可能会导致可衡量的性能差异,例如在对具有大量数据的 table 进行排序时。
引入PropertyValueFactory
的原因基本上是历史原因。在 Java 8 之前,当然没有 lambda 表达式,因此没有这种便利的细胞工厂的最小实现 class 是通过匿名内部 class:
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
确实应该被视为遗留 class,并且应该首选 lambda 表达式。当然,早于 Java 8 的文档也仍然存在(事实上,您明确地 link 来自 JavaFX 2 的文档——尽管 most recent version 仍未更新) , 并且 - 坦率地说 - 有太多其他作家在没有适当考虑的情况下复制这种风格。完全弃用 PropertyValueFactory
class 可能是一个很好的理由。
(所以:TL;DR:不,你没有遗漏任何东西。)
我正在学习 Oracle 的 JavaFX 教程。在使用 Swing 多年(很久以前)之后,我对新的智能功能非常着迷,包括。特性。我很惊讶地看到这些示例(例如:https://docs.oracle.com/javafx/2/ui_controls/table-view.htm)没有按照我认为的方式使用它们 "proper"。
该示例创建一个 Person
class,其中属性作为字段:
public static class Person {
private final SimpleStringProperty firstName;
...
但是 getter 不是针对属性,而是针对它们的值
public String getFirstName() {
return firstName.get();
}
所以当它将它们绑定到列中的 TableCell
s 时,它会将它们包装在一个新的 属性 中:
emailCol.setCellValueFactory(
new PropertyValueFactory<Person, String>("firstName"));
这对我来说似乎很复杂,并且错过了事件传播的真正优势,而不是简单地使用它:
firstNameCol.setCellValueFactory( celldata ->
celldata.getValue().firstNameProperty());
我的问题:为什么这个示例不公开并直接在控件中使用 bean 的属性是有原因的吗?我在这里遗漏了什么吗?
注意:我确实以这种方式更改了代码,并且该示例工作得更好:立即传播另一个控件在 Person
实体中的更新,w/o 调用 table.refresh()
例如
首先请注意,如果您遵循 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
更好的方法。除了您引用的原因之外,使用 lambda 表达式比 PropertyValueFactory
还具有其他主要优势。首先,也是最重要的,PropertyValueFactory
只是将 属性 的名称作为 String
,这意味着没有 compile-time 检查它。因此,如果您拼错 属性:
firstNameCol.setCellValueFactory(new PropertyValueFactory<>("firstname"));
这会编译得很好,你只会在列中得到空白单元格。这可能很难调试(本网站上寻求此类错误帮助的问题数量证明了这一点:例如 Javafx PropertyValueFactory not populating Tableview)。
其次,PropertyValueFactory
通过反射工作,这比 lambda 表达式慢得多。这可能会导致可衡量的性能差异,例如在对具有大量数据的 table 进行排序时。
引入PropertyValueFactory
的原因基本上是历史原因。在 Java 8 之前,当然没有 lambda 表达式,因此没有这种便利的细胞工厂的最小实现 class 是通过匿名内部 class:
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
确实应该被视为遗留 class,并且应该首选 lambda 表达式。当然,早于 Java 8 的文档也仍然存在(事实上,您明确地 link 来自 JavaFX 2 的文档——尽管 most recent version 仍未更新) , 并且 - 坦率地说 - 有太多其他作家在没有适当考虑的情况下复制这种风格。完全弃用 PropertyValueFactory
class 可能是一个很好的理由。
(所以:TL;DR:不,你没有遗漏任何东西。)