在TreeView中,当子CheckBoxTreeItem选中/取消选中时如何更新父CheckBoxTreeItem

时间:2019-05-24 13:37:05

标签: java javafx

我有一个带复选框的TreeItem。基本上,当我选中一个叶子复选框以强制为其所有父项执行updateItem时,我希望这样做。这是我的代码:

    package erlang.visual.tracer.gui;

import javafx.application.Application;
import javafx.css.PseudoClass;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.CheckBoxTreeCell;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

import java.net.URL;

import static javafx.scene.control.TreeItem.valueChangedEvent;

public class TreeViewLearningMain2 extends Application {

    private TreeView<String> treeView;
    private Button okButton;
    private PseudoClass leafPseudoClass = PseudoClass.getPseudoClass("leaf");
    private PseudoClass nonLeafPseudoClass = PseudoClass.getPseudoClass("non-leaf");

    @Override
    public void start(Stage stage) {

        BorderPane rootPane = new BorderPane();
        okButton = new Button("OK");
        okButton.setOnAction(this::okButtonOnAction);

        treeView = new TreeView<>();
        treeView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);

        CheckBoxTreeItem<String> rootItem = new CheckBoxTreeItem<>("Classes");
        treeView.setRoot(rootItem);
        rootItem.setIndependent(true);

        for (int i = 0; i < 3; i++) {
            CheckBoxTreeItem<String> item = new CheckBoxTreeItem<>("Class " + (i + 1));
            item.setIndependent(true);
            rootItem.getChildren().add(item);
            for (int j = 0; j < 10; j++) {
                CheckBoxTreeItem<String> innerItem = new CheckBoxTreeItem<>("Student " + (j + 1));
                innerItem.setIndependent(true);
                item.getChildren().add(innerItem);
            }
        }

        rootItem.addEventHandler(CheckBoxTreeItem.checkBoxSelectionChangedEvent(), e -> {
            if (e.getTreeItem().isLeaf()) {
                TreeItem<String> parentTreeItem = (TreeItem) e.getTreeItem().getParent();
                TreeItem.TreeModificationEvent<String> ev = new TreeItem.TreeModificationEvent<>(valueChangedEvent(), parentTreeItem);
                Event.fireEvent(parentTreeItem, ev);
            }
        });

        treeView.setCellFactory(p -> new CheckBoxTreeCell<>() {
            @Override
            public void updateItem(String item, boolean empty) {
                super.updateItem(item, empty);
                if (item != null && !item.isEmpty()) {
                    if (item.startsWith("Student")) {
                        System.out.println(String.format("updateItem(String %s, boolean %s)", item, Boolean.toString(empty)));
                        pseudoClassStateChanged(leafPseudoClass, true);
                        pseudoClassStateChanged(nonLeafPseudoClass, false);
                    } else {
                        pseudoClassStateChanged(leafPseudoClass, false);
                        pseudoClassStateChanged(nonLeafPseudoClass, true);
                    }
                }
            }
        });

        rootPane.setCenter(treeView);
        rootPane.setBottom(okButton);

        Scene scene = new Scene(rootPane, 1024, 768, Color.WHITE);

        URL style = TreeViewLearningMain2.class.getClassLoader().getResource("style.css");
        scene.getStylesheets().add(style.toExternalForm());

        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

    private void okButtonOnAction(ActionEvent e) {
        System.out.println("ok");
    }
}

请忽略CSS,这无关紧要。所以,基本上,我安装了一个用于检查叶子复选框的事件。发生这种情况时,我会为该复选框的父级触发一个事件,但是由于某种原因,每当我选中/取消选中一个叶子复选框时,我都会看到很多打印行。

例如,选中Class1中的Student1复选框会产生:

updateItem(String Student 1, boolean false)
updateItem(String Student 2, boolean false)
updateItem(String Student 3, boolean false)
updateItem(String Student 4, boolean false)
updateItem(String Student 5, boolean false)
updateItem(String Student 6, boolean false)
updateItem(String Student 7, boolean false)
updateItem(String Student 8, boolean false)
updateItem(String Student 9, boolean false)
updateItem(String Student 10, boolean false)

如您所见,每个学生都会调用更新的项目。

当我选中/取消选中一个叶子复选框时,如何使父复选框仅收到一个updateItem调用?

0 个答案:

没有答案