0

I want to add keys(Branch) of ObservableHashmap in column of TableView. So I created TableView with HashMap like that:

ObservableMap<Branch, Boolean> myMap = FXCollections.observableHashMap();
ObservableList<Branch> lst = FXCollections.observableArrayList(myMap.keySet());
this.chosenBranTable.setItems(lst);

... and defined CellValueFactory in this way:

this.chosenBranColumn.setCellValueFactory((CellDataFeatures<Branch, String> listItem) ->
{
    return new ReadOnlyObjectWrapper<String>(listItem.getValue().toString());
});

The problem is that - when I have changed myMap there is no changes in the TableView. But if I executed:

ObservableList<Branch> lst = FXCollections.observableArrayList(myMap.keySet());
this.chosenBranTable.setItems(lst);

after changing of myMap then changes in the TableView appeared. Before ObservableHashMap I used ObservableList and there was no problem with updating.

palandlom
  • 529
  • 6
  • 17

2 Answers2

0

Read the documentation:

Creates a new observable array list and adds a content of collection col to it.

Notice that it does not create an ObservableList backed by the specified Collection; it merely creates an ObservableList whose initial contents are the elements of the specified Collection.

Even if it were backed by the Collection, your goal wouldn’t be achievable, because a HashMap’s elements have no defined order. As elements are added to a HashMap, the order of the keys can and most likely will change.

One effective approach is to create an ObservableMap from a LinkedHashMap, which does preserve its order:

ObservableMap<Branch, Boolean> myMap =
    FXCollections.observableMap(new LinkedHashMap<Branch, Boolean>());

But you still need to manually make your ObservableList respond to changes in the ObservableMap:

ObservableList<Branch> lst = FXCollections.observableArrayList(myMap.keySet());
myMap.addListener(new MapChangeListener<? extends Branch, ? extends Boolean>() {
    @Override
    public void onChanged(Change<? extends Branch, ? extends Boolean> change) {
        boolean removed = change.wasRemoved();
        boolean added = change.wasAdded();
        Branch key = change.getKey();

        if (removed && !added) {
            lst.remove(key);
        }
        if (added && !removed) {
            lst.add(key);
        }
    }
});
VGR
  • 40,506
  • 4
  • 48
  • 63
  • Thank for the detailed answer . You dispelled my doubts about creating a new list which is not backed. Before that I was confused by the end of the answer: https://stackoverflow.com/questions/31916041/how-do-i-use-a-map-as-a-tableview-observablemap-object-parameter?rq=1 – palandlom Jun 09 '17 at 13:58
0

I think you need to use MapChangeListener

Like this :

private final MapChangeListener<K,V> mapChange;

 mapChange = new MapChangeListener<K, V>() {
            @Override
            public void onChanged(MapChangeListener.Change<? extends K, ? extends V> change) {
                // 
            }
        };

for more détails : https://pastebin.com/NmdTURFt

  • It seems that so. Thanks! – palandlom Jun 09 '17 at 13:43
  • Do not place the details of your answer on an external site. That URL will eventually go stale, and when it does, your answer will be of little use to future readers. – VGR Jun 09 '17 at 13:48