我有一个自定义类BasicDataSet,它包含一个需要呈现(和可更新)到JavaFX TableView的HashMap。BasicDataSet对象表示一行,该列缺少的任何散列映射值都被呈现为表中的空字符串。
BasicDataSet包含dataPoints、name和tagName的哈希映射。当ArrayList<BasicDataSet>被传递到方法中时,每个散列映射对象中的所有键都会被提取,并对重复项进行过滤。这些键将成为列标题值,并用于从哈希映射中提取数据(在工厂中)。
我的问题是创建一个这样做的单元格值工厂。这个方法应该为我的视图控制器创建一个TableView对象。
public static TableView<BasicDataSet> renderTableFromBasicDataSets(ArrayList<BasicDataSet> sets) {
TableView<BasicDataSet> tableView = new TableView<>();
// create all keys required for the collection of basic data sets
// and remove duplicates using a stream
ArrayList<String> keys = new ArrayList<>();
keys.add("name");
keys.add("tagName");
for(BasicDataSet basicDataSet : sets) {
keys.addAll(basicDataSet.getDataPointKeys());
}
keys = new ArrayList<>(keys.stream().distinct().collect(Collectors.toList()));
// create all required columns using keys to label column names
// then declare their cellValueFactories
for(String columnHeader : keys) {
TableColumn<BasicDataSet, String> tempColumn = new TableColumn<>(columnHeader);
tempColumn.setCellValueFactory(data -> {
for(BasicDataSet set : sets) {
if(columnHeader.equals("name")) {
return new ReadOnlyStringWrapper(set.getName());
} else if(columnHeader.equals("tagName")) {
return new ReadOnlyStringWrapper(set.getTagName());
} else {
final String tempVal = set.getDataPoint(columnHeader);
if(tempVal != null) {
return new ReadOnlyStringWrapper(set.getDataPoint(columnHeader));
} else {
return new ReadOnlyStringWrapper("");
}
}
}
return new ReadOnlyStringWrapper("");
});
tableView.getColumns().add(tempColumn);
}
return tableView;
}当此代码运行时,只呈现带有标头的列。没有显示任何数据。
我对Lambda的功能很陌生,所以任何关于工厂的额外细节都将不胜感激!
编辑:这里 --您将在GitHub上找到一个小示例项目。
发布于 2019-07-30 20:43:49
单元值工厂需要使用它的data参数。该参数是TableColumn请求值的实际行数据。
忽略sets。您不应该查看所有的数据,而应该只查看由data表示的一行数据。
这意味着您的代码可以简单地删除for (BasicDataSet set : sets)循环,并可以从data.getValue()获得set。
tempColumn.setCellValueFactory(data -> {
BasicDataSet set = data.getValue();
if (columnHeader.equals("name")) {
return new ReadOnlyStringWrapper(set.getName());
} else if (columnHeader.equals("tagName")) {
return new ReadOnlyStringWrapper(set.getTagName());
} else {
final String tempVal = set.getDataPoint(columnHeader);
if(tempVal != null) {
return new ReadOnlyStringWrapper(set.getDataPoint(columnHeader));
} else {
return new ReadOnlyStringWrapper("");
}
}
});理想情况下,您应该设计您的BasicDataSet类,以便它将其数据作为属性或其他可观察的值提供,这样您的单元值工厂就不必一直创建临时的“无实体”属性:
public class BasicDataSet {
private final ReadOnlyStringWrapper name = new ReadOnlyStringWrapper();
private final ReadOnlyStringWrapper tagName = new ReadOnlyStringWrapper();
private final ObservableMap<String, String> dataPoints =
FXCollections.observableHashMap();
private final ObservableSet<String> keys =
FXCollections.observableSet();
public BasicDataSet(String name,
String tagName) {
this.name.set(name);
this.tagName.set(tagName);
dataPoints.addListener(
(MapChangeListener.Change<? extends String, ? extends String> c) -> {
if (c.wasRemoved()) {
keys.remove(c.getKey());
}
if (c.wasAdded()) {
keys.add(c.getKey());
}
});
}
public ReadOnlyStringProperty nameProperty() {
return name.getReadOnlyProperty();
}
public String getName() {
return name.get();
}
public ReadOnlyStringProperty tagNameProperty() {
return tagName.getReadOnlyProperty();
}
public String getTagName() {
return tagName.get();
}
public ObservableMap<String> getObservableDataPoints() {
return dataPoints;
}
public ObservableSet<String> getDataPointKeys() {
return keys;
}
public StringBinding getObservableDataPoint(String key) {
return Bindings.stringValueAt(dataPoints, key);
}
public String getDataPoint(String key) {
return getObservableDataPoint(key).get();
}
}这允许您直接将属性传递给单元格值工厂:
tempColumn.setCellValueFactory(data -> {
BasicDataSet set = data.getValue();
if (columnHeader.equals("name")) {
return set.nameProperty();
} else if (columnHeader.equals("tagName")) {
return set.tagNameProperty();
} else {
return set.getObservableDataPoint(columnHeader);
}
});https://stackoverflow.com/questions/57278359
复制相似问题