我创建了一个带有复选框树项的TreeView。我想为每个复选框添加监听器,因此我创建了一个示例问题。但我有一些非常奇怪的行为。当我点击一个复选框时,它实际上触发了处理器本身和它上面的处理程序。
这是我写的代码:
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);
}
}
运行应用程序后,当我单击Leaf B时,它打印出来:
点击:叶子A
点击:Leaf B
我一直在试图找出为什么这种情况发生了好几天,但仍然无法找到原因。
任何提示都表示赞赏! 谢谢!
答案 0 :(得分:0)
updateItem
。这可能经常发生,并且API(故意)没有确切地指定何时(即它是实现细节)。但是,通常情况下,例如,如果用户在表格中滚动,则会经常发生。
您的updateItem()
方法每次都会向复选框添加新的侦听器,并且永远不会删除这些侦听器。所以你可能会观察到越来越多的听众被解雇,你在表格中滚动得越多。 (尝试在表中添加足够的项目以允许滚动,滚动很多,然后选中/取消选中复选框。)
预期用途是将selectedStateCallBack
设置为映射到模型类中的属性。然后,如果要对更改做出反应,可以通过观察模型中的属性来实现。这在CheckBoxTableCell changelistener not working中解释。