JavaFX:选中时未选中CheckBoxTreeItem项

时间:2017-03-31 12:09:12

标签: javafx javafx-8

在找到CheckBoxTreeItem之前,我使用了一个带有ComboBox的常规TreeItem。 CellFactory有一个onAction属性,我将其传递给CheckBox onAction方法。 onAction EventHandler来自Controller,所以当我选中/取消选中控制器中的操作方法时,调用它。问题是TreeItem没有被选中。

现在尝试使用CheckBoxTreeItem。但是我在选择和行动方面遇到了一些问题。

我需要在选中/取消选中CheckBox时执行操作。我希望复选框在选择TreeItem时更改状态。我需要在更改CheckBox时选择TreeItem。

1) 选择TreeItem不会更改CheckBox的选定状态。我不得不写一个onMousePressed动作来做到这一点。

@FXML public void performSelection() {
    TreeItem<Mine> selectedItem = treeView.getSelectionModel().getSelectedItem();
    boolean selected = ((CheckBoxTreeItem<Mine>) selectedItem).isSelected();
((CheckBoxTreeItem<Mine>) selectedItem).setSelected(!selected);
}

但是,当选中/取消选中TreeItem上的CheckBox时,不会选择该TreeItem。这不是CheckBoxTreeItem的意思吗?

2) 我创建了一个ChangeListener,它监听CheckBoxTreeItem selectedProperty的状态。此侦听器在树中的每个项目上注册。这是我可以创建一个动作来检查/取消选中的唯一方法。

但是,检查TreeItem,因为它没有选择TreeItem,我无法使用监听器中的tree.getSelectionModel()。getSelectedItem()访问它。我无法访问CheckBox项目的TreeItem数据的CheckBox操作毫无意义。如果我选择一个TreeItem,它将保留在该TreeItem上,如果我检查另一个TreeItem CheckBox,则selectedItem是错误的。

如果我选择顶部项目并且我想对该项目数据执行某些操作,则会为所有子项调用更改侦听器。这使问题复杂化。我只关心选中/未选中的所选TreeItem的状态。

没有比注册ChangeListener更好的方法来向CheckBoxTreeItem添加操作吗?

第3) 如果没有其他兄弟姐妹,取消选中该子项将取消选中父级。我不希望这样。但是,如果未选中父级,我希望孩子们“离开”/取消选中,但我不想收到通知。如果我取消选中并且有孩子,则所有孩子都应该取消选中。但是,我对未检查项目的子项目的更改事件并不感兴趣。我的问题仍然是下面的所有项目都会触发更改事件,而不仅仅是我感兴趣的项目。

我可以将每个TreeItem设置为独立的。然后在未选中时折叠展开的项目。孩子们的状态仍然独立于其父母已检查或未选中,但不会显示。

问题1是我遇到的最重要的问题。检查CheckBox需要选择该CheckBox的TreeItem。

问题2适用于ChangeListener,虽然我希望有更好的选择,并且可以通过将所有项目设置为独立来避免此处的问题。

问题3我也可以通过将所有项目设置为独立来避开,并在取消选中父项时隐藏它们。他们仍然保持着自己的状态,但是看不见了。

小型测试应用程序

package com.company;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.CheckBoxTreeItem;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.GridPane;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class MineAppTest extends Application {

    private TreeView<Mine> treeView;

    private MineChangeListener mineChangeListener = new MineChangeListener();

    public static void main(String[] argv) {
        MineAppTest.launch();
    }

    /* (non-Javadoc)
     * @see javafx.application.Application#start(javafx.stage.Stage)
     */
    @Override
    public void start(Stage primaryStage) throws Exception {
        GridPane contentPane = new GridPane();
        contentPane.getChildren().add(new Text("Hello World!"));

        treeView = new TreeView<>();
        treeView.setCellFactory(new MineTreeCellFactory());
        treeView.setOnMousePressed(event -> {
            TreeItem<Mine> selectedItem = treeView.getSelectionModel().getSelectedItem();
            boolean selected = ((CheckBoxTreeItem<Mine>)selectedItem).isSelected();
            ((CheckBoxTreeItem<Mine>)selectedItem).setSelected(!selected);
        selectedItem.setExpanded(!selected);
        });

        treeView.setShowRoot(false);

        Mine mine1 = new Mine("mine", true);
        CheckBoxTreeItem<Mine> rootItem = new CheckBoxTreeItem<>(mine1, null, true);
        rootItem.setExpanded(true);
        treeView.setRoot(rootItem);

        Mine mine2 = new Mine("test1", true);
        CheckBoxTreeItem<Mine> item1Level1 = new CheckBoxTreeItem<>(mine2, null, mine2.isEnabled());
        item1Level1.setExpanded(true);
        //item1Level1.setIndependent(true);
        item1Level1.selectedProperty().addListener(mineChangeListener);
        rootItem.getChildren().add(item1Level1);

        Mine mine3 = new Mine("subtest1", true);
        CheckBoxTreeItem<Mine> item1Level2 = new CheckBoxTreeItem<>(mine3, null, mine3.isEnabled());
        item1Level2.setExpanded(true);
        //item1Level2.setIndependent(true);
        item1Level2.selectedProperty().addListener(mineChangeListener);
        item1Level1.getChildren().add(item1Level2);

        Mine mine4 = new Mine("subtest2", true);
        CheckBoxTreeItem<Mine> item2Level2 = new CheckBoxTreeItem<>(mine4, null, mine4.isEnabled());
        item2Level2.setExpanded(true);
        //item2Level2.setIndependent(true);
        item2Level2.selectedProperty().addListener(mineChangeListener);
        item1Level1.getChildren().add(item2Level2);

        Mine mine5 = new Mine("test2", true);
        CheckBoxTreeItem<Mine> item2Level1 = new CheckBoxTreeItem<>(mine5, null, mine5.isEnabled());
        item2Level1.setExpanded(true);
        //item2Level1.setIndependent(true);
        item2Level1.selectedProperty().addListener(mineChangeListener);
        item1Level1.getChildren().add(item2Level1);

        Mine mine6 = new Mine("subtest2", true);
        CheckBoxTreeItem<Mine> item4Level2 = new CheckBoxTreeItem<>(mine6, null, mine6.isEnabled());
        item4Level2.setExpanded(true);
        //item4Level2.setIndependent(true);
        item4Level2.selectedProperty().addListener(mineChangeListener);
        item2Level1.getChildren().add(item4Level2);

        Mine mine7 = new Mine("subtest3", true);
        CheckBoxTreeItem<Mine> item5Level2 = new CheckBoxTreeItem<>(mine7, null, mine6.isEnabled());
        item5Level2.setExpanded(true);
        //item5Level2.setIndependent(true);
        item5Level2.selectedProperty().addListener(mineChangeListener);
        item4Level2.getChildren().add(item5Level2);

        contentPane.getChildren().add(treeView);

        primaryStage.setScene(new Scene(contentPane));
        primaryStage.setWidth(200);
        primaryStage.setHeight(400);
        primaryStage.setTitle("JavaFX 8 app");
        primaryStage.setOnCloseRequest(event -> Platform.exit());
        primaryStage.show();
    }

    private class MineChangeListener implements ChangeListener<Boolean>    {

        /* (non-Javadoc)
         * @see     javafx.beans.value.ChangeListener#changed(javafx.beans.value.ObservableValue, java.lang.Object, java.lang.Object)
         */
        @Override
        public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
            CheckBoxTreeItem<Mine> item = (CheckBoxTreeItem<Mine>) treeView.getSelectionModel().getSelectedItem();
            if (newValue) {
                // Do some work on the data in the selected TreeItem
            }
        }

    }

}

package com.company;

import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeView;
import javafx.scene.control.cell.CheckBoxTreeCell;
import javafx.util.Callback;

public class MineTreeCellFactory implements Callback<TreeView<Mine>, TreeCell<Mine>> {

    /* (non-Javadoc)
     * @see javafx.util.Callback#call(java.lang.Object)
     */
    @Override
    public TreeCell<Mine> call(TreeView<Mine> param) {
        CheckBoxTreeCell<Mine> cell = new CheckBoxTreeCell<Mine>() {

            /* (non-Javadoc)
             * @see javafx.scene.control.Cell#updateItem(java.lang.Object, boolean)
             */
            @Override
            public void updateItem(Mine item, boolean empty) {
                if (item == getItem() || (item != null && item.equals(getItem()))) {
                    return;
                }

                super.updateItem(item, empty);

                if (empty) {
                    setText(null);
                    setGraphic(null);
                } else {
                    if (item != null) {
                        setText(item.getName());
                    } else {
                        setText(null);
                        setGraphic(null);
                    }
                }
            }
        };
        return cell;
    }
}

package com.company;

import javafx.beans.property.SimpleBooleanProperty;

public class Mine {

    private final String name;

    private final SimpleBooleanProperty enabled;

    public Mine(String name, boolean enabled) {
        this.name = name;
        this.enabled = new SimpleBooleanProperty(enabled);
    }

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @return the description
     */
    public String getDescription() {
        return description;
    }

    public SimpleBooleanProperty enabledProperty() {
        return enabled;
    }

    /**
     * @return the isDisabled
     */
    public boolean isEnabled() {
        return enabled.get();
    }

}

0 个答案:

没有答案