JavaFX:CheckBoxTreeItem在选中时未选中

JavaFX:CheckBoxTreeItem在选中时未选中,javafx,javafx-8,Javafx,Javafx 8,在了解CheckBoxTreeItem之前,我使用了一个带有组合框的常规TreeItem。CellFactory有一个onAction属性,我将它传递到了复选框onAction方法中。onAction EventHandler来自控制器,因此当我选中/取消选中控制器中的action方法时,该方法被调用。问题是树项未被选中 现在尝试使用CheckBoxTreeItem。然而,在选择和行动方面,我有一些问题 选中/取消选中复选框后,我需要执行操作。我希望复选框在选定树项时更改状态。我需要在更改复选框

在了解CheckBoxTreeItem之前,我使用了一个带有组合框的常规TreeItem。CellFactory有一个onAction属性,我将它传递到了复选框onAction方法中。onAction EventHandler来自控制器,因此当我选中/取消选中控制器中的action方法时,该方法被调用。问题是树项未被选中

现在尝试使用CheckBoxTreeItem。然而,在选择和行动方面,我有一些问题

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

1) 选择树项不会更改复选框的选定状态。我必须写一个onmousempressed动作才能做到这一点

@FXML public void performSelection() {
    TreeItem<Mine> selectedItem = treeView.getSelectionModel().getSelectedItem();
    boolean selected = ((CheckBoxTreeItem<Mine>) selectedItem).isSelected();
((CheckBoxTreeItem<Mine>) selectedItem).setSelected(!selected);
}
@FXML public void performSelection(){
TreeItem selectedItem=treeView.getSelectionModel().getSelectedItem();
所选布尔值=((复选框TreeItem)selectedItem).isSelected();
((选中BoxTreeItem)selectedItem.setSelected(!selected);
}
但是,如果选中/取消选中树项上的复选框,则不会选中该树项。这不是CheckBoxTreeItem的重点吗

2) 我创建了一个ChangeListener,用于侦听CheckBoxTreeItem selectedProperty的状态。此侦听器在树中的每个项目上注册。这是我创建操作以对选中/未选中的项执行某些工作的唯一方法

但是,检查TreeItem时,由于它没有选择TreeItem,因此我无法使用侦听器中的tree.getSelectionModel().getSelectedItem()访问它。无法访问该复选框项的TreeItem数据的复选框操作是毫无意义的。如果我选择了一个TreeItem,它将保持在该TreeItem上,如果我选中了另一个TreeItem复选框,则selectedItem是错误的

如果我选择了最上面的项,并且希望对该项数据执行一些操作,那么会为所有子项调用更改侦听器。这使事情复杂化。我只关心选中/未选中的选定树项的状态

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

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

我可以把每棵树都独立起来。然后,在取消选中展开的项目时将其折叠。子对象的状态仍将独立于其父对象进行检查或取消检查,但将不可见

问题1是我遇到的最重要的问题。选中复选框需要选择该复选框的树项

问题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();
    }

}
package.com公司;
导入javafx.application.application;
导入javafx.application.Platform;
导入javafx.beans.value.ChangeListener;
导入javafx.beans.value.observeValue;
导入javafx.scene.scene;
导入javafx.scene.control.CheckBoxTreeItem;
导入javafx.scene.control.TreeItem;
导入javafx.scene.control.TreeView;
导入javafx.scene.layout.GridPane;
导入javafx.scene.text.text;
导入javafx.stage.stage;
公共类MineAppTest扩展了应用程序{
私人树景树景;
私有MineChangeListener MineChangeListener=新的MineChangeListener();
公共静态void main(字符串[]argv){
MineAppTest.launch();
}
/*(非Javadoc)
*@see javafx.application.application#start(javafx.stage.stage)
*/
@凌驾
public void start(Stage primaryStage)引发异常{
GridPane contentPane=新建GridPane();
contentPane.getChildren().add(新文本(“Hello World!”);
treeView=新的treeView();
setCellFactory(新的MineTreeCellFactory());
treeView.setOnMousePressed(事件->{
TreeItem selectedItem=treeView.getSelectionModel().getSelectedItem();
所选布尔值=((复选框TreeItem)selectedItem).isSelected();
((选中BoxTreeItem)selectedItem.setSelected(!selected);
selectedItem.setExpanded(!selected);
});
treeView.setShowRoot(假);
矿山1=新矿山(“矿山”,真实);
CheckBoxTreeItem rootItem=新的CheckBoxTreeItem(mine1,null,true);
setExpanded(true);
treeView.setRoot(rootItem);
矿山2=新矿山(“测试1”,正确);
CheckBoxTreeItem1Level 1=新的CheckBoxTreeItem(mine2,null,mine2.isEnabled());
Item1Level 1.setExpanded(真);
//Item1Level 1.setIndependent(真);
Item1Level 1.selectedProperty().addListener(mineChangeListener);
rootItem.getChildren().add(Item1Level 1);
矿山3=新矿山(“子测试1”,正确);
CheckBoxTreeItem1Level 2=新的CheckBoxTreeItem(mine3,null,mine3.isEnabled());
Item1Level 2.setExpanded(真);
//Item1Level 2.setIndependent(真);
Item1Level 2.selectedProperty().addListener(mineChangeListener);
Item1Level 1.getChildren().add(Item1Level 2);
矿山4=新矿山(“子测试2”,正确);
CheckBoxTreeItem2Level2=新的CheckBoxTreeItem(mine4,null,mine4.isEnabled());
Item2Level 2.setExpanded(真)