JavaFx:ListView CheckBoxListCell选择

时间:2019-06-27 10:33:48

标签: java listview javafx javafx-8

我在使用ListView的{​​{1}}时遇到了问题。当我选中/取消选中某个项目时,由于CheckBox不仅是文本部分,还是该项目的一部分,因此不会选中/突出显示该项目。

这是您可以验证的简单代码。

CheckBoxListCell

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); } @Getter private class Model { String text; BooleanProperty selected; private Model(String text, Boolean selected) { this.text = text; this.selected = new SimpleBooleanProperty(selected); } @Override public String toString() { return text; } } }

.fxml

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

任何其他想法/解决方案,当我选中/取消选中组合框时,如何选择/重点突出整个项目。

1 个答案:

答案 0 :(得分:2)

此答案仅涵盖部分问题:如何确保仅对单元格图形属性的侦听器进行一次注册(如果我们无法控制图形的设置时间)。

涉及的步骤:

  1. 定义一个InvalidationListener来安装“真实的”侦听器(注意:必须是一个字段,以后才能删除)
  2. 在实例化时间在单元格的图形属性上注册侦听器
  3. 注册“真实”方法以删除初始图形侦听器,并安装所需的任何内容

代码段(请注意:监听所选属性不是一个好主意,因为只要数据更改,不仅在用户单击复选框时,它将触发)!

listView.setCellFactory(factory -> {
    CheckBoxListCell<Model> cell = new CheckBoxListCell<Model>() {
        // a listener on the graphicProperty: it installs the "real" listener
        InvalidationListener graphicListener = g -> {
            // installs the "real" listener on the graphic control once it is available 
            registerUIListener();
        };

        {
            // install the graphic listener at instantiation
            graphicProperty().addListener(graphicListener);
        }

        /** method to install a listener on a property of the graphic control
         * and unregisters the initially installed listener
         */
        private void registerUIListener() {
            if (!(getGraphic() instanceof CheckBox)) throw new IllegalStateException("checkBox expected");
            graphicProperty().removeListener(graphicListener);
            ((CheckBox) getGraphic()).selectedProperty().addListener(
                    (observable, oldValue, newValue) -> listView.getSelectionModel().select(getItem()));
        }
    };
    cell.setSelectedStateCallback(Model::selectedProperty);
    return cell;
});