Tomas Bisciak Tomas Bisciak - 2 months ago 21
Java Question

JavaFX ListView adding item into observable list doesn't reflect change and it's not selectable

I have run into pretty messed up behaviour with my ListView, I have listview created in controller with data attached to it.

@FXML
private ListView<Weapon> listViewWeapons;
...
private final ObservableList<Loadout> loadoutList;

public LoadoutViewController() {
...
loadoutList =FXCollections.observableList(CsgoRr.getModel().getLoadoutCache());
...
}

@Override
public void initialize(URL location, ResourceBundle resources) {
...
listViewLoadouts.setItems(loadoutList);
...

}


I call method attached to button, which has function of adding new loadout into list

@FXML
private void newLoadoutOnAction() {
try {

Loadout loadoutToBeStored = new Loadout(new Long[10], "Loadout" + newDuplicateNameLoadoutIncrement);
loadoutToBeStored.setId(DbUtil.storeLoadout(loadoutToBeStored));//store and set id.
CsgoRr.getModel().getLoadoutCache().add(loadoutToBeStored);
System.out.println("Stored new loadout ");
listViewLoadouts.getSelectionModel().select(loadoutToBeStored);
for (Loadout loadout : loadoutList) {
System.out.println("DEBUG LOADOUT CONTAINER OBSERVABLE:" + loadout);
}
} catch (SQLException ex) {//duplicate name
if (ex.getErrorCode() == 23505) {
newDuplicateNameLoadoutIncrement++;
newLoadoutOnAction();
}
Logger.getLogger(LoadoutViewController.class.getName()).log(Level.SEVERE, null, ex);
}
}


All the data is correctly loaded and stored, I have debugged that part of course. But even though I call method newLoadoutOnAction and I put data into list which observable list has reference to, change is not seen up until I resize that listView. That's not the only problem, even after I resize listView and I'm able to see item in a list I can't select it I have to call construstor and initializer again to be able to select this item. I have never encountered this behaviour, how do I fix these problems?

Problem with refreshing item in the list: I have tried to remove items and set them again, and some other solutions common to this problem bud nothing worked even if I put setItems(null) I can't get it to work, items are still there.

Latest item inserted is not selectable (through UI) until I call my controller again and recreate everything. I have this item selected with code.

listViewLoadouts.getSelectionModel().select(loadoutToBeStored);


This actually selected needed item bud I don't see any feedback in the UI and I can't select it with my mouse. Even if I remove this line I still can't select it with a mouse till I call my view again (constructor and initializer).

I know this is a bit more complex problem so I decided to show you what's happening with a gif.

enter image description here

Hope it's clear.

Answer

The Javadoc for FXCollections.observableList states:

Note that mutation operations made directly to the underlying list are not reported to observers of any ObservableList that wraps it.

For this reason loadoutList is not connected to the list in CsgoRr.getModel().getLoadoutCache() after creation. This means that when newLoadoutOnAction() calls:

CsgoRr.getModel().getLoadoutCache().add(loadoutToBeStored);

it is not picked up by loadoutList, or the ListView watching it. If you change CsgoRr.getModel().getLoadoutCache() to use an ObservableList, and assign that directly to loadoutList your function should work as desired.

The other option would be to add your loadoutToBeStored to loadoutList instead, but then you would need to also synchronise with the List in CsgoRr.getModel()