JavaFx:ListView CheckBoxListCell 选择

ListView我在使用 a时遇到问题CheckBoxListCell。当我选中/取消选中某个项目时,该项目未被选中/聚焦,这是预期的,因为 CheckBox 也是该项目的一部分,而不仅仅是文本部分。


这是一个简单的代码,您可以验证它。


import javafx.beans.property.BooleanProperty;

import javafx.beans.property.SimpleBooleanProperty;

import javafx.collections.FXCollections;

import javafx.collections.ObservableList;

import javafx.fxml.FXML;

import javafx.fxml.Initializable;

import javafx.scene.control.CheckBox;

import javafx.scene.control.ListView;

import javafx.scene.control.cell.CheckBoxListCell;

import lombok.Getter;


import java.net.URL;

import java.util.ResourceBundle;


public class Controller implements Initializable {

    @FXML private ListView<Model> listView;


    @Override

    public void initialize(URL location, ResourceBundle resources) {

//      without selection

//      listView.setCellFactory(CheckBoxListCell.forListView(Model::getSelected));


        // actual "bad" solution

        listView.setCellFactory(factory -> {

            CheckBoxListCell<Model> cell = new CheckBoxListCell<Model>() {

                @Override

                public void updateItem(Model item, boolean empty) {

                    super.updateItem(item, empty);

                    if (empty) {

                        setText(null);

                        setGraphic(null);

                        return;

                    }

                    ((CheckBox) getGraphic()).selectedProperty().addListener(

                            (observable, oldValue, newValue) -> listView.getSelectionModel().select(getItem()));

                }

            };

            cell.setSelectedStateCallback(Model::getSelected);

            return cell;

        });


        ObservableList<Model> items = FXCollections.observableArrayList();


        items.add(new Model("A", true));

        items.add(new Model("B", true));

        items.add(new Model("C", false));


        listView.setItems(items);

    }

如您所见,我找到了一个解决方案,或者更确切地说是一个肮脏的解决方法,但我不太喜欢它,因为它在每个 updateItem 时都会被调用,并且它会添加 n 次监听器,这不是很好。


任何其他想法/解决方案,当我选中/取消选中组合框时,我如何才能实现这一点,整个项目都被选中/聚焦。


阿波罗的战车
浏览 378回答 1
1回答

精慕HU

这个答案只涵盖了问题的一部分:如何确保单元格图形属性的侦听器只注册一次(如果我们无法控制何时设置图形)。涉及的步骤:定义一个安装“真实”监听器的 InvalidationListener(注意:必须是一个可以稍后删除的字段)在实例化时在单元格的图形属性上注册监听器实施“真实”方法的注册以删除初始图形侦听器以及安装所需的任何东西代码片段(注意:监听 selected 属性不是一个好主意,因为它会在数据更改时触发,而不仅仅是在用户单击复选框时触发!):listView.setCellFactory(factory -> {&nbsp; &nbsp; CheckBoxListCell<Model> cell = new CheckBoxListCell<Model>() {&nbsp; &nbsp; &nbsp; &nbsp; // a listener on the graphicProperty: it installs the "real" listener&nbsp; &nbsp; &nbsp; &nbsp; InvalidationListener graphicListener = g -> {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // installs the "real" listener on the graphic control once it is available&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; registerUIListener();&nbsp; &nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // install the graphic listener at instantiation&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; graphicProperty().addListener(graphicListener);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; /** method to install a listener on a property of the graphic control&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* and unregisters the initially installed listener&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/&nbsp; &nbsp; &nbsp; &nbsp; private void registerUIListener() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!(getGraphic() instanceof CheckBox)) throw new IllegalStateException("checkBox expected");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; graphicProperty().removeListener(graphicListener);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ((CheckBox) getGraphic()).selectedProperty().addListener(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (observable, oldValue, newValue) -> listView.getSelectionModel().select(getItem()));&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; };&nbsp; &nbsp; cell.setSelectedStateCallback(Model::selectedProperty);&nbsp; &nbsp; return cell;});
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java