JavaFX CheckboxTreeItem: обрабатывать только выбранный флажок - PullRequest
3 голосов
/ 08 января 2020

Допустим, у меня есть TreeView, похожий на тот, что в примере. Когда я выбираю флажок листа (например, a1Item, a2Item), в консоли будет напечатана только одна строка. Когда я выбираю parentItem (например, rootItem, aItem), будет напечатана строка элемента и строки childItems, так как childItems будет выбран автоматически. То, что я ищу, это способ обрабатывать только выбранный флажок, но сохранить структуру и функциональность (автоматический выбор childItems) treeView.

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;
    }
}

EDIT

Я расширил дерево еще на 2 уровня, надеясь, что это поможет мне найти решение. Когда я выбираю rootItem / parentItem, я заметил, что вывод будет напечатан снизу (лист) до выбранного элемента. Но когда я выбираю, например, лист A_1_1_1, A_1_1 будет напечатан первым.

1 Ответ

0 голосов
/ 08 января 2020

Итак, для начала я не ожидаю, что вы реализуете этот точный код в своем приложении, это просто для того, чтобы дать вам представление о том, как реализовать что-то подобное. Это работает путем передачи родителя в функцию, которая строит CheckBoxTreeItem (я понимаю, вы, вероятно, не делаете этого, продолжайте чтение), чтобы каждый слушатель имел доступ к своему собственному родителю, и, делая это, мы можем проверить

  • Текущий checkBoxTreeItem выбран
  • Родитель не является нулевым, то есть он не является вершиной дерева
  • Родитель не выбран, и он не будет выбран проверка текущего 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);
    }

}

РЕДАКТИРОВАТЬ: я столкнулся с ошибкой, когда, например, вы выбираете A_1 и A_2 A будет выбирать и запускать, но снятие отметки и перепроверка либо A_1 или A_2 не перезапустит A

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...