[英]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
通过创建ObservableList
从map.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. 但是,尽管它是带有
SimpleStringProperty
的ObservableList
,但是在对基础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
一起使用,并将cellValueFactory
与Bindings.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.