JavaFX CheckboxTreeItem:仅处理所选复选框

JavaFX CheckboxTreeItem:仅处理所选复选框,javafx,Javafx,假设我有一个类似于示例中的树视图。当我选中叶子的复选框(例如a1Item、a2Item)时,控制台中只会打印一行。当我选择父项(例如rootItem、aItem)时,将打印该项的行和子项的行,因为将自动选择子项我要寻找的是一种只处理选中复选框的方法,但保留树视图的结构和功能(自动选择子项) public class Main extends Application { public static void main(String[] args) { launch(args

假设我有一个类似于示例中的树视图。当我选中叶子的复选框(例如a1Item、a2Item)时,控制台中只会打印一行。当我选择父项(例如rootItem、aItem)时,将打印该项的行和子项的行,因为将自动选择子项
我要寻找的是一种只处理选中复选框的方法,但保留树视图的结构和功能(自动选择子项)

public class Main extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        CheckBoxTreeItem<String> rootItem = createCheckBoxTreeItem("Root");
        CheckBoxTreeItem<String> aItem = createCheckBoxTreeItem("A");
        CheckBoxTreeItem<String> a1Item = createCheckBoxTreeItem("A_1");
        CheckBoxTreeItem<String> a11Item = createCheckBoxTreeItem("A_1_1");
        CheckBoxTreeItem<String> a12Item = createCheckBoxTreeItem("A_1_2");
        CheckBoxTreeItem<String> a111Item = createCheckBoxTreeItem("A_1_1_1");
        CheckBoxTreeItem<String> a2Item = createCheckBoxTreeItem("A_2");
        CheckBoxTreeItem<String> a21Item = createCheckBoxTreeItem("A_2_1");
        CheckBoxTreeItem<String> a211Item = createCheckBoxTreeItem("A_2_1_1");
        CheckBoxTreeItem<String> a22Item = createCheckBoxTreeItem("A_2_2");
        CheckBoxTreeItem<String> bItem = createCheckBoxTreeItem("B");
        CheckBoxTreeItem<String> cItem = createCheckBoxTreeItem("C");

        aItem.getChildren().addAll(a1Item, a2Item);

        rootItem.getChildren().addAll(aItem, bItem, cItem);
        rootItem.setExpanded(true);
        TreeView<String> treeView = new TreeView<>(rootItem);
        treeView.setCellFactory(CheckBoxTreeCell.<String>forTreeView());

        aItem.setExpanded(true);
        VBox vBox = new VBox(treeView);
        Scene scene = new Scene(vBox, 400, 400);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private CheckBoxTreeItem<String> createCheckBoxTreeItem(String value) {
        CheckBoxTreeItem<String> checkBoxTreeItem = new CheckBoxTreeItem<>(value);
        checkBoxTreeItem.selectedProperty().addListener((observable, oldValue, newValue) -> {
            System.out.println(checkBoxTreeItem.getValue() + " - selected: " + newValue);
        });
        return checkBoxTreeItem;
    }
}
public类主扩展应用程序{
公共静态void main(字符串[]args){
发射(args);
}
@凌驾
公共无效开始(阶段primaryStage){
CheckBoxTreeItem rootItem=创建CheckBoxTreeItem(“根”);
CheckBoxTreeItem aItem=创建CheckBoxTreeItem(“A”);
CheckBoxTreeItem a1Item=创建CheckBoxTreeItem(“A_1”);
CheckBoxTreeItem a11Item=创建CheckBoxTreeItem(“A_1_1”);
CheckBoxTreeItem A12项=创建CheckBoxTreeItem(“A_1_2”);
CheckBoxTreeItem a111Item=创建CheckBoxTreeItem(“A_1_1_1”);
CheckBoxTreeItem a2Item=创建CheckBoxTreeItem(“A_2”);
CheckBoxTreeItem a21Item=创建CheckBoxTreeItem(“A_2_1”);
CheckBoxTreeItem a211Item=创建CheckBoxTreeItem(“A_2_1_1”);
CheckBoxTreeItem A22项=创建CheckBoxTreeItem(“A_2_2”);
CheckBoxTreeItem bItem=创建CheckBoxTreeItem(“B”);
CheckBoxTreeItem cItem=创建CheckBoxTreeItem(“C”);
aItem.getChildren().addAll(a1项,a2项);
getChildren().addAll(aItem、bItem、cItem);
setExpanded(true);
TreeView TreeView=新的TreeView(根项目);
setCellFactory(CheckBoxTreeCell.forTreeView());
aItem.setExpanded(真);
VBox VBox=新的VBox(树视图);
场景=新场景(vBox,400400);
初级阶段。场景(场景);
primaryStage.show();
}
私有CheckBoxTreeItem createCheckBoxTreeItem(字符串值){
CheckBoxTreeItem CheckBoxTreeItem=新的CheckBoxTreeItem(值);
checkBoxTreeItem.selectedProperty().addListener((可观察、旧值、新值)->{
System.out.println(checkBoxTreeItem.getValue()+“-选中:”+newValue);
});
返回checkBoxTreeItem;
}
}
编辑


我将树扩展了2级,希望这能帮助我找到解决方案。当我选择rootItem/parentItem时,我注意到输出将从底部(叶)一直打印到所选项目。但当我选择例如叶子A_1_1_1时,会首先打印A_1_1

首先,我不希望您在应用程序中实现这段代码,这只是为了让您了解如何实现类似的东西。它的工作方式是将父对象传递给正在构建CheckBoxTreeItem的函数(我知道您可能不这样做,请继续阅读),这样每个侦听器都可以访问自己的父对象,通过这样做,我们可以进行检查

  • 选中当前复选框TreeItem
  • 父级不为null,表示它不是树的顶部
  • 未选择父项,也不会通过选中当前的checkBoxTreeItem来选择父项
这使我们能够决定是否应该执行必要的代码。重要的一点是,您希望检查的代码上的侦听器可以访问父级,以便确定是否需要启动

这是我的解决办法

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) {
        CheckBoxTreeItem rootItem = buildNewCheckBoxTreeItem("Root", null);
        CheckBoxTreeItem aItem = buildNewCheckBoxTreeItem("A", rootItem);
        CheckBoxTreeItem a1Item = buildNewCheckBoxTreeItem("A_1", aItem);
        CheckBoxTreeItem a2Item = buildNewCheckBoxTreeItem("A_2", aItem);
        CheckBoxTreeItem bItem = buildNewCheckBoxTreeItem("B", rootItem);
        CheckBoxTreeItem cItem = buildNewCheckBoxTreeItem("C", rootItem);

        aItem.getChildren().addAll(a1Item, a2Item);

        rootItem.getChildren().addAll(aItem, bItem, cItem);
        rootItem.setExpanded(true);
        TreeView<String> treeView = new TreeView<>(rootItem);
        treeView.setCellFactory(CheckBoxTreeCell.<String>forTreeView());

        aItem.setExpanded(true);
        VBox vBox = new VBox(treeView);
        Scene scene = new Scene(vBox, 400, 400);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private CheckBoxTreeItem buildNewCheckBoxTreeItem(String text, CheckBoxTreeItem parentCheckBoxTreeItem){
        CheckBoxTreeItem<String> checkBoxTreeItem = new CheckBoxTreeItem<>(text);

        checkBoxTreeItem.selectedProperty().addListener((observable) -> {
            if(shouldFireListener(checkBoxTreeItem, parentCheckBoxTreeItem))
                System.out.println(checkBoxTreeItem.getValue());
        });

        return checkBoxTreeItem;
    }

    private boolean shouldFireListener(CheckBoxTreeItem checkBoxTreeItem, CheckBoxTreeItem parentCheckBoxTreeItem){
        if(checkBoxTreeItem.isSelected()){
            if(parentCheckBoxTreeItem!=null) {
                if (!parentCheckBoxTreeItem.isSelected() && !goingToBeSelected(parentCheckBoxTreeItem))
                    return true;
            }
            else
                return true;
        }
        return false;
    }

    private boolean goingToBeSelected(CheckBoxTreeItem parent){
        ArrayList<CheckBoxTreeItem> childrenArraylist = new ArrayList<>();

        for (Object child : parent.getChildren()) {
            if(child instanceof CheckBoxTreeItem)
                childrenArraylist.add(((CheckBoxTreeItem) child));
        }

        return childrenArraylist.stream().allMatch(CheckBoxTreeItem::isSelected);
    }

}
public类主扩展应用程序{
@凌驾
公共无效开始(阶段primaryStage){
CheckBoxTreeItem rootItem=buildNewCheckBoxTreeItem(“根”,null);
CheckBoxTreeItem aItem=buildNewCheckBoxTreeItem(“A”,根项);
CheckBoxTreeItem a1Item=buildNewCheckBoxTreeItem(“A_1”,aItem);
CheckBoxTreeItem a2Item=buildNewCheckBoxTreeItem(“A_2”,aItem);
CheckBoxTreeItem bItem=buildNewCheckBoxTreeItem(“B”,根项);
CheckBoxTreeItem cItem=buildNewCheckBoxTreeItem(“C”,rootItem);
aItem.getChildren().addAll(a1项,a2项);
getChildren().addAll(aItem、bItem、cItem);
setExpanded(true);
TreeView TreeView=新的TreeView(根项目);
setCellFactory(CheckBoxTreeCell.forTreeView());
aItem.setExpanded(真);
VBox VBox=新的VBox(树视图);
场景=新场景(vBox,400400);
初级阶段。场景(场景);
primaryStage.show();
}
私有CheckBoxTreeItem buildNewCheckBoxTreeItem(字符串文本,CheckBoxTreeItem parentCheckBoxTreeItem){
CheckBoxTreeItem CheckBoxTreeItem=新的CheckBoxTreeItem(文本);
checkBoxTreeItem.selectedProperty().addListener((可观察)->{
if(shouldFireListener(checkBoxTreeItem、parentCheckBoxTreeItem))
System.out.println(checkBoxTreeItem.getValue());
});
返回checkBoxTreeItem;
}
私有布尔值shouldFireListener(CheckBoxTreeItem CheckBoxTreeItem,CheckBoxTreeItem parentCheckBoxTreeItem){
if(checkBoxTreeItem.isSelected()){
if(parentCheckBoxTreeItem!=null){
如果(!parentCheckBoxTreeItem.isSelected()&&!将被选中(parentCheckBoxTreeItem))
返回true;
}
其他的
返回true;
}
返回false;
}
已选择私有布尔值(CheckBoxTreeItem父项){
ArrayList childrenArraylist=新建ArrayList();
对于(对象子对象:parent.getChildren()){
if(CheckBoxTreeItem的子实例)
childrenArraylist.add(((CheckBoxTreeItem)child));
}
返回childrenArraylist.stream().allMatch(CheckBoxTreeItem::isSelected);
}
}
编辑:我遇到了一个错误,例如,你选择了一个1和一个2,a将选择并启动,但取消选中