简体   繁体   English

使用HashMap填充TableView,该列表将在HashMap更改时更新

[英]Populating a TableView with a HashMap that will update when HashMap changes

I have followed this post 我已经关注了这篇文章

Binding hashmap with tableview (JavaFX) 使用TableView绑定哈希图(JavaFX)

and created a TableView that is populated by data from a HashMap. 并创建了一个TableView,该表由HashMap中的数据填充。

The TableView receives its data from a HashMap called map by creating an ObservableList from map.entrySet() and handing that ObservableList off to the TableView 's constructor. 所述TableView从接收其数据HashMap称为map通过创建ObservableListmap.entrySet()和移交该ObservableList关闭的TableView的构造。 (Code is below) (代码如下)

However, although it's an ObservableList with SimpleStringProperty s, the TableView does not update when changes are made to the underlying HashMap. 但是,尽管它是带有SimpleStringPropertyObservableList ,但是在对基础HashMap进行更改时,TableView不会更新。

Here is my code: 这是我的代码:

public class MapTableView extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        try {
            // sample data
            Map<String, String> map = new HashMap<>();
            map.put("one", "One");
            map.put("two", "Two");
            map.put("three", "Three");


            // use fully detailed type for Map.Entry<String, String> 
            TableColumn<Map.Entry<String, String>, String> column1 = new TableColumn<>("Key");
            column1.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Map.Entry<String, String>, String>, ObservableValue<String>>() {

                @Override
                public ObservableValue<String> call(TableColumn.CellDataFeatures<Map.Entry<String, String>, String> p) {
                    // this callback returns property for just one cell, you can't use a loop here
                    // for first column we use key
                    return new SimpleStringProperty(p.getValue().getKey());
                }
            });

            TableColumn<Map.Entry<String, String>, String> column2 = new TableColumn<>("Value");
            column2.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Map.Entry<String, String>, String>, ObservableValue<String>>() {

                @Override
                public ObservableValue<String> call(TableColumn.CellDataFeatures<Map.Entry<String, String>, String> p) {
                    // for second column we use value
                    return new SimpleStringProperty(p.getValue().getValue());
                }
            });

            ObservableList<Map.Entry<String, String>> items = FXCollections.observableArrayList(map.entrySet());
            final TableView<Map.Entry<String,String>> table = new TableView<>(items);

            table.getColumns().setAll(column1, column2);

            Button changeButton = new Button("Change");
            changeButton.setOnAction((ActionEvent e) -> {
                map.put("two", "2");
                System.out.println(map);
            });
            VBox vBox = new VBox(8);
            vBox.getChildren().addAll(table, changeButton);

            Scene scene = new Scene(vBox, 400, 400);
            stage.setScene(scene);
            stage.show();
        }  catch(Exception e) {
            e.printStackTrace();
        }
    } 

    public static void main(String[] args) {
        launch();
    }

}

This is exactly the code from Binding hashmap with tableview (JavaFX) except I have added the following button: 这正是来自使用tableview绑定哈希图(JavaFX)的代码,除了我添加了以下按钮之外:

        Button changeButton = new Button("Change");
        changeButton.setOnAction((ActionEvent e) -> {
            map.put("two", "2");
            System.out.println(map);
        });

which I then add to a VBox with the TableView. 然后我将其添加到带有TableView的VBox中。

When I click the button, the TableView is not updated. 当我单击按钮时, TableView不会更新。 However, I can verify that the underlying HashMap has indeed changed because of the System.out.println(map) output. 但是,我可以验证由于System.out.println(map)输出,基础HashMap确实发生了更改。 Also when I click on a column header in the TableView to sort the data by one column, the new updated value appears after the table data is re-sorted. 同样,当我单击TableView的列标题以按一列对数据进行排序时,在对表数据进行重新排序之后,将显示新的更新值。

How can I make the table update automatically when the underlying map is changed? 更改基础地图时,如何使表自动更新?

Thank you, 谢谢,

Mark 标记

Use an ObservableMap with a listener that keeps the TableView items and the keys of the map the same and use the cellValueFactory with Bindings.valueAt , eg: ObservableMap与使TableView项和地图的键保持不变的cellValueFactory一起使用,并将cellValueFactoryBindings.valueAt cellValueFactory使用,例如:

ObservableMap<String, String> map = FXCollections.observableHashMap();

ObservableList<String> keys = FXCollections.observableArrayList();

map.addListener((MapChangeListener.Change<? extends String, ? extends String> change) -> {
    boolean removed = change.wasRemoved();
    if (removed != change.wasAdded()) {
        // no put for existing key
        if (removed) {
            keys.remove(change.getKey());
        } else {
            keys.add(change.getKey());
        }
    }
});

map.put("one", "One");
map.put("two", "Two");
map.put("three", "Three");

final TableView<String> table = new TableView<>(keys);

TableColumn<String, String> column1 = new TableColumn<>("Key");
// display item value (= constant)
column1.setCellValueFactory(cd -> Bindings.createStringBinding(() -> cd.getValue()));

TableColumn<String, String> column2 = new TableColumn<>("Value");
column2.setCellValueFactory(cd -> Bindings.valueAt(map, cd.getValue()));

table.getColumns().setAll(column1, column2);

This will update your tableView. 这将更新您的tableView。

changeButton.setOnAction(e -> {
                map.put("two", "2");
                table.getColumns().setAll(column1, column2);
                System.out.println(map);
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM