Javafx:如何用地图填充 TableView?

Javafx: How to populate a TableView with a map?

我在尝试使用 map 填充 TableView 时遇到问题。我一直在看关于堆栈溢出和其他页面的不同类型的问题,但我的大脑似乎没有得到它。

我有一个 class,它包含一个以产品名称为键、以正常价格为值的地图。我创建了一个 table 视图,其中包含名称列和价格主列,分为正常列和新列两列,如下所示。

public class CreatePricesPane extends GridPane {
    private TableView table = new TableView<>();
    private PriceList tempPriceList;


    public CreatePricesPane(){
        this.tempPriceList = Controller.getController().createPriceList();
        this.setPadding(new Insets(20));
        this.setHgap(70);
        this.setVgap(10);
        this.setGridLinesVisible(false);
//        this.setPrefSize(800, 500);
        this.setStyle("-fx-background-color: #fff");

        //All about table
        this.table.setEditable(true);
        this.table.setItems(this.generateData());
        TableColumn<Map,String> nameColumn = new TableColumn("Names");
        nameColumn.setMinWidth(300);

        TableColumn pricesColumn = new TableColumn("Prices");

        TableColumn<Map,Double> normalPriceColumn = new TableColumn("Normal price");
        normalPriceColumn.setMinWidth(150);
//        normalPriceColumn.setCellValueFactory(new MapValueFactory<>());

        TableColumn newPriceColumn = new TableColumn("New price");
        newPriceColumn.setMinWidth(150);

        pricesColumn.getColumns().addAll(normalPriceColumn,newPriceColumn);


        table.setEditable(true);
        table.getSelectionModel().setCellSelectionEnabled(true);
        table.getColumns().setAll(nameColumn, pricesColumn);

我用这个方法把Map变成了ObservableList。

    private ObservableList<Map<String, Double>> generateData(){
        ObservableList<Map<String,Double>> alldata = FXCollections.observableArrayList();

        Map<String, Double> map = new HashMap(this.tempPriceList.getPriceListMap());

        for (Map.Entry<String, Double> entry : map.entrySet()) {
            Map<String, Double> dataRow = new HashMap<>();
            dataRow.put(entry.getKey(), entry.getValue());
            alldata.add(dataRow);
        }
        return alldata;
    }

这就是我卡住的地方。我不知道如何用这个 ObservableList 填充每个单元格。我知道我必须以某种方式使用“setCellFactory”。有没有人对如何制作最后的代码有任何建议?或者向正确的方向发送我?

提前致谢!

这是我迄今为止尝试过的方法。但实际上我无法理解下面这段代码中发生的事情。我希望它会在开始时用名称填充 table。运气不好。

        Callback<TableColumn<Map, String>, TableCell<Map, String>>
                cellFactoryForMap = new Callback<TableColumn<Map, String>,
                TableCell<Map, String>>() {
            @Override
            public TableCell call(TableColumn p) {
                return new TextFieldTableCell(new StringConverter() {
                    @Override
                    public String toString(Object t) {
                        return t.toString();
                    }
                    @Override
                    public Object fromString(String string) {
                        return string;
                    }
                });
            }
        };

nameColumn.setCellFactory(cellFactoryForMap);

为您的 TableView 项创建真正的数据类型。

public class Item {
    private final StringProperty name;
    private final DoubleProperty price;
    private final DoubleProperty newPrice;

    public Item() {
        name = new SimpleStringProperty(this, "name");
        price = new SimpleDoubleProperty(this, "price");
        newPrice = new SimpleDoubleProperty(this, "newPrice");
    }

    public Item(String name,
                double price) {
        this();
        setName(name);
        setPrice(price);
    }

    public StringProperty nameProperty() {
        return name;
    }

    public String getName() {
        return name.get();
    }

    public void setName(String name) {
        this.name.set(name);
    }

    public DoubleProperty priceProperty() {
        return price;
    }

    public double getPrice() {
        return price.get();
    }

    public void setPrice(double price) {
        this.price.set(price);
    }

    public DoubleProperty newPriceProperty() {
        return newPrice;
    }

    public double getNewPrice() {
        return newPrice.get();
    }

    public void setNewPrice(double price) {
        this.newPrice.set(price);
    }
}

(注意:在现实世界的应用程序中,程序员不应该使用 double 来表示金额,因为 float 和 double 是不精确的数字,可能会丢失信息。BigDecimal 是表示的正确类型钱。)

现在您的 TableColumns 的单元格值工厂变得容易得多:

nameColumn.setCellValueFactory(f -> f.getValue().nameProperty());
pricesColumn.setCellValueFactory(f -> f.getValue().priceProperty());
newPriceColumn.setCellValueFactory(f -> f.getValue().newPriceProperty());

创建这些项目与您已经在做的非常相似,尽管更简单:

private ObservableList<Item> generateData() {
    ObservableList<Item> alldata = FXCollections.observableArrayList();

    for (Map.Entry<String, Double> entry : map.entrySet()) {
        alldata.add(new Item(entry.getKey(), entry.getValue()));
    }

    return alldata;
}