如何使用变更侦听器JavaFX在两个ListView之间移动项目 [英] How to move items between two ListViews with change listener JavaFX
问题描述
我有两个ListView
,allStudentsList
中已经填充了项目,currentStudentList
中没有任何项目.我的目的是当用户在allStudentList
中选择一个项目时将其移动到currentStudentList
中.通过在allStudentList
的选择模型上放置一个侦听器来完成此操作.
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
.
我得到一个IndexOutOfBoundsException
,我不确定为什么会这样.从测试来看,这个问题似乎仅限于此方法的最后4行,但我不确定为什么.
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);
}
});
推荐答案
作为快速解决方案,您可以将修改项目列表的代码部分包装到Platform.runLater(...)
块中:
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);
});
问题在于,在处理选择更改时无法更改选择.当您使用allStudentsList.getItems().clear();
删除所有元素时,选择将更改(所选索引将为-1
),上述条件将得到满足.这就是Platform.runLater(...)
块的用法将通过推迟"修改来防止的.
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);
});
}
});
它将选择的索引设置为-1
:ListView
中未选择任何内容,以避免在删除当前项时更改为其他项(这在您的版本中是通过清除列表来隐式完成的),然后添加将当前选择的元素添加到选定列表"中,然后从所有项目列表"中删除当前元素.所有这些动作都包装在提到的Platform.runLater(...)
块中.
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.
这篇关于如何使用变更侦听器JavaFX在两个ListView之间移动项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!