I have two ListView
s, allStudentsList
has items already populated within it, currentStudentList
has none. My aim for when the user selects an item in allStudentList
is for that item be moved into currentStudentList
. I have done this by placing a listener on the selection model of the allStudentList
.
I get an IndexOutOfBoundsException
and I am not sure why this is occurring. From testing, it seems that this problem is isolated to the last 4 lines of this method yet I am not sure why.
allStudentsList.getSelectionModel().selectedItemProperty()
.addListener((observableValue, oldValue, newValue) -> {
if (allStudentsList.getSelectionModel().getSelectedItem() != null) {
ArrayList<String> tempCurrent = new ArrayList<>();
for (String s : currentStudentList.getItems()) {
tempCurrent.add(s);
}
ArrayList<String> tempAll = new ArrayList<>();
for (String s : allStudentsList.getItems()) {
tempAll.add(s);
}
tempAll.remove(newValue);
tempCurrent.add(newValue);
// clears current studentlist and adds the new list
if (currentStudentList.getItems().size() != 0) {
currentStudentList.getItems().clear();
}
currentStudentList.getItems().addAll(tempCurrent);
// clears the allStudentList and adds the new list
if (allStudentsList.getItems().size() != 0) {
allStudentsList.getItems().clear();
}
allStudentsList.getItems().addAll(tempAll);
}
});
As a quick fix you can wrap the code parts that modify the item lists into a Platform.runLater(...)
block:
Platform.runLater(() -> {
// clears current studentlist and adds the new list
if (currentStudentList.getItems().size() != 0)
currentStudentList.getItems().clear();
currentStudentList.getItems().addAll(tempCurrent);
});
Platform.runLater(() -> {
// clears the allStudentList and adds the new list
if (allStudentsList.getItems().size() != 0)
allStudentsList.getItems().clear();
allStudentsList.getItems().addAll(tempAll);
});
The problem is that you cannot change the selection while a selection change is being processed. As you remove all elements with allStudentsList.getItems().clear();
, the selection will change (the selected index will be -1
), the mentioned condition will met. This is what the usage of the Platform.runLater(...)
block will prevent by "postponing" the modification.
But your whole handler could be exchanged with
allStudentsList.getSelectionModel().selectedItemProperty().addListener((obs, oldValue, newValue) -> {
if (newValue != null) {
Platform.runLater(() -> {
allStudentsList.getSelectionModel().select(-1);
currentStudentList.getItems().add(newValue);
allStudentsList.getItems().remove(newValue);
});
}
});
It sets the selected index to -1
: nothing is selected in the ListView
to avoid changing to a different item when removing the current one (this was done implicitly in your version by clearing the list), then it adds the currently selected element to the s"elected list", then it removes the current element from the "all item list". All of these actions are wrapped in the mentioned Platform.runLater(...)
block.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With