Java 使用HashMap填充TableView,该HashMap将在HashMap更改时更新
我关注过这个帖子 并创建了一个由HashMap中的数据填充的TableViewJava 使用HashMap填充TableView,该HashMap将在HashMap更改时更新,java,javafx,hashmap,tableview,observablelist,Java,Javafx,Hashmap,Tableview,Observablelist,我关注过这个帖子 并创建了一个由HashMap中的数据填充的TableView TableView通过从map.entrySet()创建一个observeList并将该observeList关闭到TableView的构造函数,从名为map的HashMap接收数据。(代码如下) 但是,尽管它是一个带有SimpleStringPropertys的ObservableList,但当对基础HashMap进行更改时,TableView不会更新 这是我的密码: public class MapTableV
TableView
通过从map.entrySet()
创建一个observeList
并将该observeList
关闭到TableView
的构造函数,从名为map
的HashMap
接收数据。(代码如下)
但是,尽管它是一个带有SimpleStringProperty
s的ObservableList
,但当对基础HashMap进行更改时,TableView不会更新
这是我的密码:
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();
}
}
然后将其添加到带有TableView的VBox中
单击按钮时,TableView
不会更新。但是,我可以验证底层的HashMap
确实因为System.out.println(map)
输出而发生了更改。另外,当我单击TableView
中的列标题按一列对数据进行排序时,表数据重新排序后会出现新的更新值
当基础映射发生更改时,如何使表自动更新
谢谢,
标记这将更新您的tableView
changeButton.setOnAction(e -> {
map.put("two", "2");
table.getColumns().setAll(column1, column2);
System.out.println(map);
});
使用
observeMap
和监听器,使TableView
项和映射键保持相同,并使用cellValueFactory
和,例如:
observeMap=FXCollections.observeHashMap();
ObservableList keys=FXCollections.observableArrayList();
map.addListener((mapchangeStener.change)我没有详细研究这一点,但也许你想使用一个。也许这个答案谢谢。这确实有效。但是,如果我向表中添加一些东西呢?例如,如果我将行map.put(“二”,“二”)
更改为map.put(“四”,“四”)
。在这种情况下,表不会更新以反映更改。为什么不更新?不管怎样,我现在知道为什么了。因此我可以将行table.getColumns().setAll(column1,column2)
更改为table.setItems(FXCollections.observearraylist(map.entrySet());
但这似乎不美观,因为我正在重新创建ArrayList并用它重新填充表。此外,这样做会“破坏”用户通过单击列标题可能已经建立的任何排序顺序。还有其他方法吗?对于>=8u60的版本,您可能应该替换getColumns().getColumns().setAll(第1列、第2列)
withrefresh()
谢谢。效果很好!这是一种有趣的方法,将它变成一个字符串表,并为键提供一个单独的ObservableList。我也不知道MapChangeListener和绑定。非常有用,谢谢!我正在尝试理解lambda表达式中的绑定。假设我现在想为observeMap
其中Shade
是一个自定义类,具有名为Description
的StringProperty
成员(即getDescription()
返回一个String
和descriptionProperty()
返回一个StringProperty
)如何更改行column2.setCellValueFactory(cd->Bindings.valueAt(map,cd.getValue())
?感谢您提供的见解。不幸的是,绑定API没有提供这种2级绑定,因此您必须通过向映射值的相应属性添加侦听器(并在值更改为其他值时将其从旧值的属性中删除)来自行编程.没有那么复杂,但评论部分不是给出更详细描述的合适位置。
changeButton.setOnAction(e -> {
map.put("two", "2");
table.getColumns().setAll(column1, column2);
System.out.println(map);
});
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);