我有一个ObservableMap
,我想绑定到tableview,以显示映射值的一些属性,但映射中的新值未显示。在搜索和谷歌搜索我发现大部分相同的代码,但没有解决方案。绑定到TableView的ObservableMap不会更新新值
继承人是解释这个问题,唯一的解决方案',我发现一个SSCCE:创建一个新的ObservableList
与地图的值,并将其设置为表每次地图上的变化,这是不是一个很棒的解决
public class MapTableBindTest extends Application {
int personIDCounter;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
personIDCounter = 0;
// Map - TableView binding
ObservableMap<Integer, Person> map = FXCollections.observableHashMap();
Person first = new Person("First", "Person"); // this person is mapped before the bind to the table
map.put(first.getID(), first); // and because that, is shown on it
ObservableList<Map.Entry<Integer, Person>> list = FXCollections.observableArrayList(map.entrySet());
TableView<Map.Entry<Integer, Person>> table = new TableView<>(list);
Person second = new Person("Second", "Person"); // once the bind has been setted no new items
map.put(second.getID(), second); // are shown on the table. Same case when added in the UI
// Columns
TableColumn<Map.Entry<Integer, Person>, String> nameCol = new TableColumn<>("Name");
nameCol.setCellValueFactory(cellData -> cellData.getValue().getValue().getName());
TableColumn<Map.Entry<Integer, Person>, String> lastNameCol = new TableColumn<>("Surname");
lastNameCol.setCellValueFactory(cellData -> cellData.getValue().getValue().getSurname());
table.getColumns().addAll(nameCol, lastNameCol);
// View
BorderPane root = new BorderPane();
TextField nameField = new TextField();
TextField lastNameField = new TextField();
Button addButton = new Button("Add");
addButton.setOnMouseClicked(event -> {
Person newP = new Person(nameField.getText(), lastNameField.getText());
map.put(newP.getID(), newP); // new items are not populated in the table...
nameField.clear();
lastNameField.clear();
// ... unless a new observable list is created and setted to the table
ObservableList<Map.Entry<Integer, Person>> auxiliarList = FXCollections.observableArrayList(map.entrySet());
table.setItems(auxiliarList);
// commenting this two lines result with no updates shown in the table
});
HBox TextHB = new HBox(nameField, lastNameField, addButton);
root.setTop(TextHB);
root.setCenter(table);
Scene scene = new Scene(root,400,500);
primaryStage.setScene(scene);
primaryStage.show();
}
// Sample class with some properties
class Person {
private int id;
private StringProperty name, surname;
public Person(String name, String surname) {
id = personIDCounter++;
this.name = new SimpleStringProperty(name);
this.surname = new SimpleStringProperty(surname);
}
public int getID() {
return id;
}
public StringProperty getName() {
return name;
}
public StringProperty getSurname() {
return surname;
}
}
}
可能什么是错与对ObservableList
地图的entryset()
之间的绑定。 Javadoc中说,大约entrySet()
的ObservableMap
的:
返回包含在此映射中的映射关系的Set视图。 该集合由地图支持,因此对地图的更改将反映在集合中,反之亦然。(...)
这不是很明显,否则TableView会随着更改而更新。
解(感谢James_D): 上ObservableMap
此侦听添加/删除表中所示ObservableList
,因此值的变化。当您添加项目,并通过entrySet()
返回集也改变
map.addListener((MapChangeListener.Change<? extends Integer, ? extends Person> c) -> {
if (c.wasAdded()) {
Person added = c.getValueAdded();
list.add(new AbstractMap.SimpleEntry<Integer, Person>(added.getID(), added));
} else if (c.wasRemoved()) {
Person removed = c.getValueRemoved();
list.remove(new AbstractMap.SimpleEntry<Integer, Person>(removed.getID(), removed));
}
});
谢谢!我正在尝试使用'Bindings'类,我想这可能是一些解决方法,使用javafx的预定义绑定 - 属性 - 监听器。我用解决方案编辑了这个问题 – ottogarcia