代码之家  ›  专栏  ›  技术社区  ›  Light

javafx tableview列复选框侦听器

  •  -1
  • Light  · 技术社区  · 6 年前

    我有带复选框的TableColumn。我必须做这个监听器,我想知道为什么监听器在每次点击后都会加倍。

        selectedColumn.setCellFactory(column -> new CheckBoxTableCell<>());
        selectedColumn.setCellValueFactory(cellData -> {
            Dir dir = cellData.getValue();
            BooleanProperty property = dir.isSelectedProperty();
    
            property.addListener((ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) ->{
                System.out.println(newValue);
            });
    
            return property;
        });
    

    第一次单击复选框i行返回: 真的 真的

    第二次取消选择返回: 假 假 假 假

    三次选择返回: 真的 真的 真的 真的 真的 真的

    为什么?:)

    2 回复  |  直到 6 年前
        1
  •  2
  •   Jai    6 年前

    这是因为控件 TableView (和 ListView 等)虚拟化其内容。从TableView Javadoc:

    tableview控件设计为 想象无限数量的 数据行 ,分成几列。

    这个 表格视图 可能存放大量物品。但是,在屏幕上,您可能会在任何时间点看到10-30行(每行对应于一个项目)。

    如果没有虚拟化,如果您有100万个项目,它将创建100万个 TableRow 对象(我们还没有讨论 TableCell ),每个 表格行 维护所有状态/值。这需要 很多 记忆和处理能力。

    另一方面,使用虚拟化,如果视图只能显示10行, 表格视图 只会创建,例如,12 表格行 实例。当你在列表中滚动时,一些项目会从你的视线中消失这些 表格行 实例会立即重新用于进入您视线的项目。

    这就是为什么 setCellFactory() setCellValueFactory() 方法是 Callback 键入。每次重用一行时,它都会调用此回调对象来更新 表格单元 是的。这就是为什么你的监听器被重复添加,从而导致这种情况。

    根据您的需要,可以添加 ListChangedListener 到项目列表。

    ObservableList<Dir> list = FXCollections.observableArrayList(item -> new javafx.beans.Observable[] {item.isSelectedProperty()});
    list.addAll(DirList.getDirList());
    dirList.setItems(list);
    
    list.addListener(new ListChangeListener<Dir>() {
        @Override public void onChanged(javafx.collections.ListChangeListener.Change<? extends Dir> c) {
            while (c.next()) {
                if (c.wasUpdated()) {
                    // Do something
                }
            }
        }
    });
    
        2
  •  1
  •   Sunflame    6 年前

    我看到你有个模特叫 Dir 用一个 BooleanProperty 命名的 selected

    你可以让 cellValueFactory 只是:

    selectedColumn.setCellValueFactory(cellData -> cellData.getValue().isSelectedProperty());

    如果选中/取消选中 CheckBox 在表格单元格中。

    如果使用复选框的选中/取消选中状态,则可以使用模型,并在其中添加侦听器,您将得到相同的结果。然后只添加一次侦听器。

    你应该有 董事 创建,然后您可以为ex in执行以下操作 initialize 以下内容:

    dir1.selectedProperty().addListener((observable, oldValue, newValue) -> {
                dir2.selectedProperty().set(oldValue);
            });
    

    或者你想要的任何东西,那么你就确定只添加了一次监听器。 正如@Jai所提到的,每次 CallBack 如果要避免多次将侦听器添加到属性中,请不要在该方法中使用侦听器。