使用HashMap填充TableView,HashMap将在HashMap更改时更新
我关注过这篇文章
使用tableview绑定hashmap(JavaFX)
并创建了一个由HashMap数据填充的TableView。
TableView
通过从map.entrySet()
创建一个ObservableList
并将该ObservableList
移交给TableView
的构造函数,从名为map
的HashMap
接收其数据。 (代码如下)
但是,虽然它是带有SimpleStringProperty
的ObservableList
,但是当对底层HashMap进行更改时,TableView不会更新。
这是我的代码:
public class MapTableView extends Application { @Override public void start(Stage stage) throws Exception { try { // sample data Map map = new HashMap(); map.put("one", "One"); map.put("two", "Two"); map.put("three", "Three"); // use fully detailed type for Map.Entry TableColumn<Map.Entry, String> column1 = new TableColumn("Key"); column1.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Map.Entry, String>, ObservableValue>() { @Override public ObservableValue call(TableColumn.CellDataFeatures<Map.Entry, 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> column2 = new TableColumn("Value"); column2.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Map.Entry, String>, ObservableValue>() { @Override public ObservableValue call(TableColumn.CellDataFeatures<Map.Entry, String> p) { // for second column we use value return new SimpleStringProperty(p.getValue().getValue()); } }); ObservableList<Map.Entry> items = FXCollections.observableArrayList(map.entrySet()); final TableView<Map.Entry> 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(); } }
这正是来自Binding hashmap with tableview(JavaFX)的代码,除了我添加了以下按钮:
Button changeButton = new Button("Change"); changeButton.setOnAction((ActionEvent e) -> { map.put("two", "2"); System.out.println(map); });
然后我将其添加到带有TableView的VBox中。
单击该按钮时, TableView
不会更新。 但是,由于System.out.println(map)
输出,我可以validation底层HashMap
确实已更改。 此外,当我单击TableView
的列标题以按一列对数据进行排序时,在重新排序表数据后会出现新的更新值。
如何在更改基础地图时自动更新表格?
谢谢,
标记
使用带有监听器的ObservableMap
,该监听器保持TableView
项和映射的键相同,并将cellValueFactory
与Bindings.valueAt
cellValueFactory
使用,例如:
ObservableMap map = FXCollections.observableHashMap(); ObservableList 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 table = new TableView<>(keys); TableColumn column1 = new TableColumn<>("Key"); // display item value (= constant) column1.setCellValueFactory(cd -> Bindings.createStringBinding(() -> cd.getValue())); TableColumn column2 = new TableColumn<>("Value"); column2.setCellValueFactory(cd -> Bindings.valueAt(map, cd.getValue())); table.getColumns().setAll(column1, column2);
这将更新你的tableView。
changeButton.setOnAction(e -> { map.put("two", "2"); table.getColumns().setAll(column1, column2); System.out.println(map); });