JavaFXTreeView错误行为

JavaFXTreeView错误行为,javafx,javafx-2,javafx-8,Javafx,Javafx 2,Javafx 8,我创建了一个带有复选框树项的树视图。我想将侦听器添加到每个复选框中,所以我创建了一个示例问题。但我有一些很奇怪的行为。当我点击一个复选框时,它实际上触发了它本身和它上面的处理程序 以下是我编写的代码: package sample; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.*; import javafx.scene.control.cell.CheckBoxT

我创建了一个带有复选框树项的树视图。我想将侦听器添加到每个复选框中,所以我创建了一个示例问题。但我有一些很奇怪的行为。当我点击一个复选框时,它实际上触发了它本身和它上面的处理程序

以下是我编写的代码:

package sample;

import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.control.cell.CheckBoxTreeCell;
import javafx.scene.layout.AnchorPane;
import java.net.URL;
import java.util.ResourceBundle;

public class Controller implements Initializable{
  @FXML
  public AnchorPane container;

  public static class CustomTreeCell extends CheckBoxTreeCell<String> {
    @Override
    public void updateItem(String item, boolean empty) {
      super.updateItem(item, empty);
      if (empty) {
        setText(null);
        setGraphic(null);
      } else {
        setText(item);
        ((CheckBox) getGraphic()).selectedProperty().addListener(((observable, oldValue, newValue) -> {
          System.out.println("Clicked on: " + item);
        }));
      }
    }
  }

  @Override
  public void initialize(URL location, ResourceBundle resources) {
    TreeView<String> treeView = new TreeView<>();
    treeView.setCellFactory((TreeView<String> param) -> new CustomTreeCell());
    container.getChildren().add(treeView);
    CheckBoxTreeItem root = new CheckBoxTreeItem<>("Root");
    treeView.setRoot(root);
    CheckBoxTreeItem leaf_A = new CheckBoxTreeItem<>("Leaf A");
    CheckBoxTreeItem leaf_B = new CheckBoxTreeItem<>("Leaf B");
    CheckBoxTreeItem leaf_C = new CheckBoxTreeItem<>("Leaf C");
    root.getChildren().addAll(leaf_A, leaf_B, leaf_C);
  }
}
包装样品;
导入javafx.fxml.fxml;
导入javafx.fxml.Initializable;
导入javafx.scene.control.*;
导入javafx.scene.control.cell.CheckBoxTreeCell;
导入javafx.scene.layout.ancorpane;
导入java.net.URL;
导入java.util.ResourceBundle;
公共类控制器实现可初始化{
@FXML
公共锚烷容器;
公共静态类CustomTreeCell扩展了CheckBoxTreeCell{
@凌驾
public void updateItem(字符串项,布尔值为空){
super.updateItem(项,空);
if(空){
setText(空);
设置图形(空);
}否则{
setText(项目);
((复选框)getGraphic()).selectedProperty().addListener(((可观察、旧值、新值)->{
System.out.println(“单击:+项”);
}));
}
}
}
@凌驾
公共void初始化(URL位置、ResourceBundle资源){
TreeView TreeView=新的TreeView();
setCellFactory((treeView参数)->new CustomTreeCell());
container.getChildren().add(treeView);
CheckBoxTreeItem root=新的CheckBoxTreeItem(“根”);
树丛根(根);
CheckBoxTreeItem leaf_A=新的CheckBoxTreeItem(“leaf A”);
CheckBoxTreeItem leaf_B=新的CheckBoxTreeItem(“leaf B”);
CheckBoxTreeItem leaf_C=新的CheckBoxTreeItem(“leaf C”);
root.getChildren().addAll(叶A、叶B、叶C);
}
}
运行应用程序后,当我单击Leaf B时,它会打印出以下内容:

点击:叶A
点击:叶B

几天来我一直在试图弄清楚为什么会发生这种情况,但仍然找不出原因

任何提示都将不胜感激!
谢谢

updateItem
在重复使用单元格以显示不同项目时被调用。这种情况经常发生,API(故意)没有指定确切的时间(即,这是一个实现细节)。但是,通常情况下,如果用户在表格中滚动,这种情况会频繁发生

您的
updateItem()
方法每次都会将新的侦听器添加到复选框中,并且从不删除这些侦听器。因此,您可能会观察到,您在表中滚动的次数越多,就会有越来越多的侦听器被解雇。(尝试向表中添加足够的项目以允许滚动,滚动很多,然后选中/取消选中复选框。)

预期用途是将设置为映射到模型类中的属性。然后,如果要对更改做出反应,可以通过观察模型中的属性来实现。这在。

((复选框)getGraphic()).setOnAction(事件->系统.out.println(“单击:+项))而不是监听选择更改。