首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TableColumn #setCellValueFactory用于HashMaps类

TableColumn #setCellValueFactory用于HashMaps类
EN

Stack Overflow用户
提问于 2019-07-30 18:55:09
回答 1查看 233关注 0票数 0

我有一个自定义类BasicDataSet,它包含一个需要呈现(和可更新)到JavaFX TableViewHashMapBasicDataSet对象表示一行,该列缺少的任何散列映射值都被呈现为表中的空字符串。

BasicDataSet包含dataPoints、name和tagName的哈希映射。当ArrayList<BasicDataSet>被传递到方法中时,每个散列映射对象中的所有键都会被提取,并对重复项进行过滤。这些键将成为列标题值,并用于从哈希映射中提取数据(在工厂中)。

我的问题是创建一个这样做的单元格值工厂。这个方法应该为我的视图控制器创建一个TableView对象。

代码语言:javascript
复制
    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上找到一个小示例项目。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-07-30 20:43:49

单元值工厂需要使用它的data参数。该参数是TableColumn请求值的实际行数据。

忽略sets。您不应该查看所有的数据,而应该只查看由data表示的一行数据。

这意味着您的代码可以简单地删除for (BasicDataSet set : sets)循环,并可以从data.getValue()获得set

代码语言:javascript
复制
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类,以便它将其数据作为属性或其他可观察的值提供,这样您的单元值工厂就不必一直创建临时的“无实体”属性:

代码语言:javascript
复制
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();
    }
}

这允许您直接将属性传递给单元格值工厂:

代码语言:javascript
复制
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);
    }
});
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57278359

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档