Use a texfield to search/filter an treeview

2019-07-26 14:41发布

i have been trying to find an answer to this but it seems like hell of a complicated to do.

What i want to do is that i have a treeview and with an textfield i want to be able to search so only the treeitems in the treeview that matches whats on the textfield shows.

for example if someone writes "lat" in the textfield the treeview shows folders like "latency" "latvia" and so on.

the treeview fill code is as this

@FXML
private void fillTreeView() {
    // The tree needs a root, and it needs to be a DocumentObject
    // so we create an empty folder and hide it
    TreeItem<DocumentObject<?>> treeRoot = new TreeItem<>(new Folder());

    for (Folder folder : logic.getFolderList()) {
        TreeItem<DocumentObject<?>> folderNode = new TreeItem<>(folder);

        for (FileReference file : folder.getFileList()) {
            TreeItem<DocumentObject<?>> fileNode = new TreeItem<>(file);
            folderNode.getChildren().add(fileNode);
        }

        treeRoot.getChildren().add(folderNode);
        treeRoot.setExpanded(true);
    }

    treeNav.setRoot(treeRoot);
    treeNav.setShowRoot(false);
}

and then i want the Textfield to seach both treeitems and display what the user searched for

1条回答
孤傲高冷的网名
2楼-- · 2019-07-26 15:04

If you are only filtering the direct children of the root node, it's fairly straightforward. Just keep the top level nodes in a separate ObservableList, wrap a FilteredList around it, and then use Bindings.bindContent() to make sure the child node list of the root node contains the same elements as the FilteredList.

Assuming your DocumentObject has a method, say getName() that returns the text against which you want to apply the filter, and you have a TextField called textField where the user types the filter text, this would look something like:

@FXML
private void fillTreeView() {
    // The tree needs a root, and it needs to be a DocumentObject
    // so we create an empty folder and hide it
    TreeItem<DocumentObject<?>> treeRoot = new TreeItem<>(new Folder());

    ObservableList<TreeItem<DocumentObject<?>>> firstLevel = FXCollections.observableArrayList();

    for (Folder folder : logic.getFolderList()) {
        TreeItem<DocumentObject<?>> folderNode = new TreeItem<>(folder);

        for (FileReference file : folder.getFileList()) {
            TreeItem<DocumentObject<?>> fileNode = new TreeItem<>(file);
            folderNode.getChildren().add(fileNode);
        }

        firstLevel.add(folderNode);
    }

    treeRoot.setExpanded(true);


    FilteredList<TreeItem<DocumentObject<?>>> filteredList = new FilteredList<>(firstLevel, item -> true);

    filteredList.predicateProperty().bind(Bindings.createObjectBinding(() -> {
        String filter = textField.getText();
        if (filter.isEmpty()) return item -> true ;
        return item -> item.getValue().getName().startsWith(filter) ; // your implementation may vary...
    }, textField.textProperty());

    Bindings.bindContent(treeRoot.getChildren(), filteredList);

    treeNav.setRoot(treeRoot);
    treeNav.setShowRoot(false);
}

If you want to filter the entire tree, then you need to do the same at each level....

查看更多
登录 后发表回答