Search code examples
javajavafxtreeviewjavafx-8

How to search JavaFX TreeView for next TreeItem?


I would like to setup some search functionality so that when you type text into a TextField and press enter it finds the first instance of that String in a TreeView. Then, when you press enter again, it will finds the second instance, pressing it again will find the third, ect...

It doesn't seem too hard to be able to search a TreeView and find the first TreeItem containing text, but I am unsure how to then keep searching down the TreeView for other TreeItems containing said text. I imagine to search through all the Folders/Documents inside a TreeView would require some sort of recursive function, but am unsure. I would therefore like to ask if anyone might be able to provide an example or some tips of how to create this search functionality. Any help would be appreciated :)

Drew


Solution

  • You could a recurive function to search through the tree.

    In the below code I have maintained 1 instance variable it holds the number of times searchBtn has been clicked, although this solves the question, its not quite optimal, when the user clicks the search button again although it gets the next match, it traverses the tree from the beginning (not from the previous match), you could use this as a solution for now, I will try to come up with a more optimal solution in the mean time

     public class TreeViewSample extends Application {
    
    private int count=0;
    
    private TreeView<String> tree;
    public static void main(String[] args) {
        launch(args);
    }
    
    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Tree View Sample");        
    
    
        TextField txtField=new TextField();
        Button searchBtn=new Button("Search");
    
        txtField.setOnAction(new EventHandler<ActionEvent>() {
    
            @Override
            public void handle(ActionEvent arg0) {
                count=0;
            }
        });
        TreeItem<String> rootItem = new TreeItem<String> ("Root");
        rootItem.setExpanded(true);
    
        TreeItem<String> item1 = new TreeItem<String> ("Child 1");
        TreeItem<String> item12 = new TreeItem<String> ("Child 12");
        item1.getChildren().add(item12);
        TreeItem<String> item2 = new TreeItem<String> ("Child 2");
        TreeItem<String> item21 = new TreeItem<String> ("Child 21");
        item2.getChildren().add(item21);
        TreeItem<String> item211 = new TreeItem<String> ("Child 12");
        item21.getChildren().add(item211);
        TreeItem<String> item3 = new TreeItem<String> ("Child 3");
        TreeItem<String> item31 = new TreeItem<String> ("Child 12");
        item3.getChildren().add(item31);
        rootItem.getChildren().addAll(item1,item2,item3);
        searchBtn.setOnAction(new EventHandler<ActionEvent>() {
    
            @Override
            public void handle(ActionEvent arg0) {
                count++;
                handleSearch(rootItem,txtField.getText());
    
            }
        });
        this.tree = new TreeView<String> (rootItem);    
    
        VBox root = new VBox();
        root.getChildren().addAll(tree,txtField,searchBtn);
        primaryStage.setScene(new Scene(root, 300, 250));
        primaryStage.show();
    }
    
    protected int handleSearch(TreeItem<String> rootItem, String text) {
        int count=0;
        if(rootItem!=null&&rootItem.getValue().equals(text)){
            tree.getSelectionModel().select(rootItem);
            return 1;
        }
        if(rootItem!=null&&!rootItem.getChildren().isEmpty()){
            for(TreeItem<String> treeItem: rootItem.getChildren()){
                count+=handleSearch(treeItem, text);
                if(this.count==count){
                    break;
                }
            }
        }
        return count;
    }
    }
    

    Note that you could also use a tree iterator and iterate it in a loop, if you don't want to use recursions