我不会抑制“未经检查”的警告:没有理由不正确输入您的TableView
and TableColumn
s.
The setCellValueFactory(...)
中的方法TableColumn
不需要采取PropertyValueFactory
: 可以采取任何Callback<CellDataFeatures<S>, ObservableValue<T>>
. Here S
是表格每行显示的数据类型(即您正在使用TableView<S>
), and T
是此列中显示的数据类型(即您正在使用TableColumn<S,T>
)。在你的情况下S
is Trainee
and T
is Number
.
This Callback
本质上只是一个将给定行值(在您的情况下为 Trainee)转换为要在单元格中显示的值的函数。它变得稍微复杂一些,因为行值被包装在CellDataFeatures
对象,并且返回类型必须是ObservableValue
包装要显示的实际值。 ACellDataFeatures
如果您想要访问其他信息来计算您的价值(它使您可以访问TableColumn
其中正在显示值并且TableView
其中TableColumn
举行)。一个ObservableValue
需要返回作为TableCell
将观察值的变化并自动更新。
如果您只想要行值,而不关心知道哪个TableView
or TableColumn
你在(或者已经知道,这很常见),你得到行值(Trainee
在你的例子中)通过调用getValue()
on the CellDataFeatures
object.
如果您没有ObservableValue
(例如Property
)对于您的值,您可以将常规值包装在其中之一中ReadOnlyXXXWrapper
类。
所以基本上你需要的是Callback
实施其call(...)
方法根据行的值计算要显示的值。
在你的例子中,call()
方法只需引用地图:
traineeCol.setCellValueFactory(new Callback<CellDataFeatures<Trainee>, ObservableValue<Number>>() {
@Override
public ObservableValue<Number> call(CellDataFeatures<Trainee> data) {
Integer value = data.getValue().getTrainingPassed().get(course.getName());
if (value == null) {
value = 0 ;
}
return new ReadOnlyIntegerWrapper(value);
}
});
在 Java 8 中,这减少为
traineeCol.setCellValueFactory(data ->
new ReadOnlyIntegerWrapper(data.getValue().getTrainingPassed().getOrDefault(course.getName(),0)));
The PropertyValueFactory
在许多示例中使用的只是一个预定义的实现,它使用反射来查找所提供的对象中返回可观察值的现有方法。它所做的事情的基本逻辑在Javadocs http://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/cell/PropertyValueFactory.html。恕我直言,它在 Java 8 中相当多余,因为你可以替换
firstNameColumn.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
with
firstNameColumn.setCellValueFactory(data -> data.getValue().firstNameProperty());
后者不太容易出错(一切都经过编译器检查:方法返回的类型以及存在这种方法的事实)并且执行速度更快(反射通常相当慢)。