如何使用更改侦听器 JavaFX 在两个 ListView 之间移动项目

Posted

技术标签:

【中文标题】如何使用更改侦听器 JavaFX 在两个 ListView 之间移动项目【英文标题】:How to move items between two ListViews with change listener JavaFX 【发布时间】:2017-02-04 12:11:05 【问题描述】:

我有两个ListViews,allStudentsList 中已经填充了项目,currentStudentList 没有。当用户在allStudentList 中选择一个项目时,我的目标是将该项目移动到currentStudentList。我通过在allStudentList 的选择模型上放置一个监听器来做到这一点。

我收到了IndexOutOfBoundsException,但我不确定为什么会发生这种情况。从测试来看,这个问题似乎与该方法的最后 4 行有关,但我不知道为什么。

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);
            
        );

【问题讨论】:

哪一行抛出异常? allStudents.getItems().clear(); allStudentsList.getItems().addAll(tempAll); 【参考方案1】:

作为一种快速修复,您可以将修改项目列表的代码部分包装到 Platform.runLater(...) 块中:

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(...) 块的使用将通过“推迟”修改来防止的。

但你的整个处理程序可以交换

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 中没有选择任何内容,以避免在删除当前项时更改为不同的项(这是通过清除列表在您的版本中隐式完成的),然后添加当前选择的元素到 s“选定列表”,然后它从“所有项目列表”中删除当前元素。所有这些操作都包含在提到的Platform.runLater(...) 块中。

【讨论】:

以上是关于如何使用更改侦听器 JavaFX 在两个 ListView 之间移动项目的主要内容,如果未能解决你的问题,请参考以下文章

如何监视 ObservableList JavaFX 中包含的对象的更改

JavaFX - 属性“无效”的含义

JavaFx TableView 列不填充 TableView 宽度

如何使某些JavaFX TreeView节点不可选择?

如何在没有侦听器的情况下获取 javafx 媒体元数据

清理 JavaFX 属性侦听器和绑定(内存泄漏)