AJJ
AJJ

Reputation: 3628

JavaFX CheckBoxTreeItem Selection

I have a javafx checkbox tree. I need to select the checkbox when the tree item is clicked. I have added a listener for the selection property of the tree view. But the listener gets fired only when the tree item is clicked. The above listener is not fired when the checkbox is clicked.

Required: A listener that fires when a tree item or checkbox is clicked in the treeview.

Code:

String memberArray = {"subChild1", "subChild2", "childSub1"}
Group groupRoot = new Group();
Scene scene = new Scene(groupRoot, Color.ALICEBLUE);
HBox hBox = new HBox();
hBox.setMaxWidth(fxPanel.getWidth());
final Label royalLabel = new Label("Select a item");

TreeSet<String> prefixMember = new TreeSet<String>();
String tmpName = null;
LinkedHashSet<CheckBoxTreeItem<String>> treeItems = new LinkedHashSet<CheckBoxTreeItem<String>>();
LinkedHashSet<CheckBoxTreeItem<String>> treeSubItems = new LinkedHashSet<CheckBoxTreeItem<String>>();

for (String item : memberArray) {
    if (!item.isEmpty()) {
        tmpName = item.substring(0, 3);
        prefixMember.add(tmpName);
    }
}

// Create and empty TreeView
TreeView<String> duckTree = new TreeView<String>();

// Create TreeItems for the Hierarchy of the TreeView
CheckBoxTreeItem<String> root = new CheckBoxTreeItem<String>("Parent");
CheckBoxTreeItem<String> lm1 = new CheckBoxTreeItem<String>("Child1");
CheckBoxTreeItem<String> lm2 = new CheckBoxTreeItem<String>("Child2");

for (String item : prefixMember) {
    CheckBoxTreeItem<String> treeItem = new CheckBoxTreeItem<String>(item.toString());
    for (String subItem : memberArray) {
        if (!subItem.isEmpty() && subItem.substring(0, 3).equals(item)) {
            CheckBoxTreeItem<String> treeSubItem = new CheckBoxTreeItem<String>(
                        subItem.toString());
                    treeSubItems.add(treeSubItem);
        }
    }
    treeItems.add(treeItem);
    treeItem.getChildren().addAll(treeSubItems);
    treeSubItems.clear();
}

root.getChildren().addAll(treeItems);
treeItems.clear();

// Create a TreeView using the root TreeItem
TreeView<String> royalTree = new TreeView<String>(root);
royalTree.setCellFactory(CheckBoxTreeCell.<String>forTreeView());

// Set a ChangeListener to handle events that occur with a Treeitem
// is selected
royalTree.getSelectionModel().selectedItemProperty()
        .addListener(new ChangeListener<TreeItem<String>>() {
            public void changed(
                    ObservableValue<? extends TreeItem<String>> observableValue,
                    TreeItem<String> oldItem, TreeItem<String> newItem) {
                // Gets fired only on selection of tree item
                // Need to get fired on selection of check box too
                // Select the respective checkbox on selection of tree item
            }
        });

hBox.getChildren().add(royalTree);
groupRoot.getChildren().add(hBox);
fxPanel.setScene(scene);

Upvotes: 1

Views: 5450

Answers (4)

prasad_
prasad_

Reputation: 14317

Yes, adding an event handler to the tree item works. Here is some example code (Java 8) with a TreeView with items as CheckBoxTreeItem:

CheckBoxTreeItem<Path> rootItem = new CheckBoxTreeItem<>(rootDirPath);
rootItem.addEventHandler(
        CheckBoxTreeItem.<Path>checkBoxSelectionChangedEvent(), 
        (TreeModificationEvent<Path> e) -> {
    CheckBoxTreeItem<Path> item = e.getTreeItem();  
    if (item.isSelected() || item.isIndeterminate()) {
        System.out.println("Some items are checked");
    }
    else {
        System.out.println("Some items are unchecked");
    }       
});
TreeView<Path> tree = new TreeView<>(rootItem);
tree.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);

Upvotes: 1

herculanodavi
herculanodavi

Reputation: 228

You could just add an EventHandler to your root item in the tree:

rootItem.addEventHandler(CheckBoxTreeItem.checkBoxSelectionChangedEvent(), new EventHandler<TreeModificationEvent<Object>>() {

            @Override
            public void handle(TreeModificationEvent<Object> event) {
                // Your code here.
            }
        });

Upvotes: 2

Kalaschni
Kalaschni

Reputation: 2438

i had the same problem and searched looong time. Sadly there is not offical documentation for this from oracle.

The answer is to set the CellFactory and call the getSelectedStateCallback().call(this.getTreeItem());
for your treeItem in the updateItem:

// set cellFactory
royalTree.setCellFactory(new Callback<TreeView<String>, TreeCell<String>>() {
    @Override
    public TreeCell<String> call(TreeView<String> p) {
        // return new CheckBoxTreeCell, you also can make a new class with this
        return new CheckBoxTreeCell<String>() {
            @Override
            public void updateItem(String item, boolean empty) {
                super.updateItem(item, empty);
                if (!empty) {
                    // call the selectedStat Callback for treeitem
                    ObservableValue<Boolean> selectedState = getSelectedStateCallback().call(this.getTreeItem());
                    if (selectedState != null) {
                        // do something here
                    }
                }
            }
        };
    }
});

i have tested this in fx 8, but it should also work in fx 2.2

happy coding,
kalasch

Upvotes: 1

SamHuman
SamHuman

Reputation: 186

Do you require an event for each selection immediately? If not you can create an arraylist of all your checkboxtreeitems and iterate through that to check for selected or not selected when you need it.

Upvotes: 0

Related Questions