【问题标题】:How to add listener to the checkbox inside a listview that uses CheckBoxListCell如何将侦听器添加到使用 CheckBoxListCell 的列表视图中的复选框
【发布时间】:2014-10-10 10:11:18
【问题描述】:

我有一个列表视图,它使用CheckBoxListCell 在项目旁边显示一个带有复选框的列表。如何向此复选框添加侦听器以了解项目何时被选中或未选中?

【问题讨论】:

    标签: java listview javafx


    【解决方案1】:

    解决方案

    您不会向复选框添加侦听器。通过CheckBoxListCell.forListView 例程将侦听器添加到与复选框关联的对象的可观察属性中。

    建立关联:

    ListView<Task> checklist = new ListView<>(tasks);
    checklist.setCellFactory(CheckBoxListCell.forListView(Task::selectedProperty));
    

    为所有项目添加监听器:

    tasks.forEach(task -> task.selectedProperty().addListener((observable, wasSelected, isSelected) -> {
        if (isSelected) {
            // . . .
        } else {
            // . . .
        }
    }));
    

    文档

    该过程在CheckBoxListCell.forListView javadoc 中描述如下:

    getSelectedProperty - 一个回调,给定一个类型为 T 的对象 (这是从 ListView.items 列表中取出的值),将 返回一个 ObservableValue,表示给定的 项目是否被选中。这个 ObservableValue 将被绑定 双向(意味着单元格中的 CheckBox 将设置/取消设置 此属性基于用户交互,并且 CheckBox 将 反映 ObservableValue 的状态,如果它在外部发生变化)。

    示例程序

    一个示例程序,演示了可以与 CheckBoxListCell 一起使用的一些模式:

    import javafx.application.Application;
    import javafx.beans.property.*;
    import javafx.collections.*;
    import javafx.geometry.Insets;
    import javafx.scene.Scene;
    import javafx.scene.control.ListView;
    import javafx.scene.control.cell.CheckBoxListCell;
    import javafx.scene.layout.HBox;
    import javafx.stage.Stage;
    import javafx.util.StringConverter;
    
    import java.util.*;
    import java.util.stream.Collectors;
    
    public class CheckList extends Application {
        @Override
        public void start(Stage stage) throws Exception{
            ObservableList<Task> tasks = FXCollections.observableArrayList(
                    Arrays.stream(taskNames).map(Task::new).collect(Collectors.toList())
            );
    
            ListView<String> reactionLog = new ListView<>();
            tasks.forEach(task -> task.selectedProperty().addListener((observable, wasSelected, isSelected) -> {
                if (isSelected) {
                    reactionLog.getItems().add(reactionStrings.get(task.getName()));
                    reactionLog.scrollTo(reactionLog.getItems().size() - 1);
                }
            }));
    
            ListView<Task> checklist = new ListView<>(tasks);
            checklist.setCellFactory(CheckBoxListCell.forListView(Task::selectedProperty, new StringConverter<Task>() {
                @Override
                public String toString(Task object) {
                    return object.getName();
                }
    
                @Override
                public Task fromString(String string) {
                    return null;
                }
            }));
    
            HBox layout = new HBox(10, checklist, reactionLog);
            layout.setPrefSize(350, 150);
            layout.setPadding(new Insets(10));
            Scene scene = new Scene(layout);
            stage.setScene(scene);
            stage.show();
        }
    
        public static class Task {
            private ReadOnlyStringWrapper name = new ReadOnlyStringWrapper();
            private BooleanProperty selected = new SimpleBooleanProperty(false);
    
            public Task(String name) {
                this.name.set(name);
            }
    
            public String getName() {
                return name.get();
            }
            public ReadOnlyStringProperty nameProperty() {
                return name.getReadOnlyProperty();
            }
    
            public BooleanProperty selectedProperty() {
                return selected;
            }
            public boolean isSelected() {
                return selected.get();
            }
            public void setSelected(boolean selected) {
                this.selected.set(selected);
            }
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    
        private static final String[] taskNames = {
                "Walk the dog",
                "Skin the cat",
                "Feed the pig"
        };
    
        private static final Map<String, String> reactionStrings = new HashMap<>();
        static {
            reactionStrings.put("Walk the dog", "The dog thanks you");
            reactionStrings.put("Skin the cat", "The cat hates you");
            reactionStrings.put("Feed the pig", "The pig wants more");
        }
    }
    

    选择第一项和三次选择第三项后的示例输出。

    【讨论】:

    • 非常感谢@jewelsea
    【解决方案2】:

    如果项目还没有指示它是否已被选中的属性,这里是一个替代方案:

    public class CheckedListViewCheckObserver<T> extends SimpleObjectProperty<Pair<T, Boolean>> {
    
        BooleanProperty getObserverForObject(T object) {
            BooleanProperty value = new SimpleBooleanProperty(false);
            value.addListener((observable, oldValue, newValue) -> {
                CheckedListViewCheckObserver.this.set(new Pair<>(object, newValue));
            });
            return value;
        }
    }
    

    然后要使用它,您只需:

    CheckedListViewCheckObserver observer = new CheckedListViewCheckObserver<>();
    checklist.setCellFactory(CheckBoxListCell.forListView(observer::getObserverForObject));
    

    现在你可以设置一个监听器来监听任何变化:

    observer.addListener((obs, old, curr) -> {
        if (curr.getValue()) {
            System.out.println("You have checked " + curr.getKey());
        } else {
            System.out.println("You have unchecked " + curr.getKey());
        }
    });
    

    这种方法的优点是不依赖于所使用的对象;相反,由于它是通用的,你可以简单地将它附加到一个已经存在的列表视图上,它就可以开始工作了。

    希望这对某人有所帮助。

    【讨论】:

      猜你喜欢
      • 2018-07-13
      • 1970-01-01
      • 1970-01-01
      • 2011-06-01
      • 2015-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多