javafx listView selectionItemproperty未在ClearSelection上启动(索引)



我正在使用javafx作为我正在编写的应用程序的GUI。我的GUI中有一个listView和一个按钮。

我希望ListView在单击鼠标上维护多个选择,并且仅在再次单击时删除选择(这起作用(。

我还需要验证ListView中选择了某些内容,并在启用了任何启用时禁用该按钮(可以在选择中使用,但不能在拆卸上使用(。

这是我的按钮启用和禁用的代码(这是不起作用的(:

//Binding used to enable and disable the button
    BooleanBinding validEntriesBinding = new BooleanBinding(){
        {
            super.bind(listView.getSelectionModel().selectedItemProperty());
        }
        @Override
        protected boolean computeValue() {
            log.info("No individual item selected? " + 
                    (listView.getSelectionModel().getSelectedItems().isEmpty()));
            log.info("Selected items: " + listView.getSelectionModel().getSelectedItems().toString());
            return (listView.getSelectionModel().getSelectedItems().isEmpty());
        }
    };
    button.disableProperty().bind(validEntriesBinding);

这是我用于捕获鼠标选择的代码(这是有效的,从此 so 回答Fabian的解决方案(:

//Example sourced from stackoverflow.com/questions/40900478/mimicking-ctrlclick-multiple-selection-in-listview-using-javafx
        //Answer by fabian
        //Must use MouseEvent.MOUSE_PRESSED and not MOUSE_CLICKED, otherwise the selection does not work
        listView.addEventFilter(MouseEvent.MOUSE_PRESSED, event -> {
            Node node = event.getPickResult().getIntersectedNode();
            while(node != null && node != listView && !(node instanceof ListCell)){
                node = node.getParent();
            }
            if(node instanceof ListCell){
                event.consume();
                listView.requestFocus();
                ListCell cell = (ListCell) node;
                if(!cell.isEmpty()){
                    if(cell.isSelected()){
                        log.info("Clear selection...");
                          listView.getSelectionModel().clearSelection(cell.getIndex());
                              log.info("Selection cleared");
                    }
                    else{
                          log.info("Selecting...");
                        listView.getSelectionModel().select(cell.getIndex());
                        log.info("Selected");
                    }
                }
                else{
                    log.warn("Cell is empty... cannot select");
                }
            }
            else{
                log.warn("Unable to handle event for " + node.getId() + " " + node.getClass());
            }
        });

这是我运行应用程序时输出的样子:

    //Before click, button disabled
    No individual item selected? true
    Selected items: []
    //First click selecting a cell, button enabled
    Selecting...
    No individual item selected? false
    Selected items: [SV124]
    Selected
    //Second click deselecting the first selected cell, button stays
    //enabled as the BooleanBinding never fires
    Clear selection...
    Selection cleared

为什么BooleanBinding不在listView.getSelectionModel().clearSelection(cell.getIndex());上发射?或者,更直接,为什么选择为空时listView.getSelectionModel().selectedItemProperty()不发射?根据Javadoc的说法,它应该在空时返回null,所以不应该被捕获吗?

似乎从列表视图的选择模型中删除所选 index 无法使selectedItemProperty()无效。(这似乎是一个错误。(

如果您绑定到 selectedIndexProperty而不是 selectedItemProperty

,它可以工作
BooleanBinding validEntriesBinding = new BooleanBinding(){
    {
        super.bind(listView.getSelectionModel().selectedIndexProperty());
    }
    @Override
    protected boolean computeValue() {
        log.info("No individual item selected? " + 
                (listView.getSelectionModel().getSelectedItems().isEmpty()));
        log.info("Selected items: " + listView.getSelectionModel().getSelectedItems().toString());
        return (listView.getSelectionModel().getSelectedItems().isEmpty());
    }
};

也许,由于您启用了多个选择,因此无论如何都可以绑定到选定项目的 list

BooleanBinding validEntriesBinding = new BooleanBinding(){
    {
        super.bind(listView.getSelectionModel().getSelectedItems());
    }
    @Override
    protected boolean computeValue() {
        log.info("No individual item selected? " + 
                (listView.getSelectionModel().getSelectedItems().isEmpty()));
        log.info("Selected items: " + listView.getSelectionModel().getSelectedItems().toString());
        return (listView.getSelectionModel().getSelectedItems().isEmpty());
    }
};

请注意,如果将validEntriesBinding作为局部变量,则容易出现意外垃圾收集。您应该将其作为字段:

private BooleanBinding validEntriesBinding ;
// ...
validEntriesBinding = new BooleanBinding(){
    {
        super.bind(listView.getSelectionModel().getSelectedItems());
    }
    @Override
    protected boolean computeValue() {
        log.info("No individual item selected? " + 
                (listView.getSelectionModel().getSelectedItems().isEmpty()));
        log.info("Selected items: " + listView.getSelectionModel().getSelectedItems().toString());
        return (listView.getSelectionModel().getSelectedItems().isEmpty());
    }
};

最新更新