Drew B
Drew B

Reputation: 465

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

Upvotes: 4

Views: 2189

Answers (2)

garawaa garawaa
garawaa garawaa

Reputation: 310

If other treeitem contains same child it may works wrong way. For ex:

  • root -> Department -> Worker
  • root -> Store -> Worker

In this case if I want search store worker it selects department worker.

So I added some mod to the function. May useful for someone

protected boolean handleSearch(TreeItem<String> rootItem, String text, String parent) {
    boolean found = false;
    if (rootItem != null && rootItem.getValue().equals(text) && rootItem.getParent() != null && rootItem.getParent().getValue().equals(parent)) {
        mainTree.getSelectionModel().select(rootItem);
        return true;
    }

    if (rootItem != null && !rootItem.getChildren().isEmpty()) {
        for (TreeItem<String> treeItem : rootItem.getChildren()) {
            found = handleSearch(treeItem, text, parent);
            if (found) {
                break;
            }
        }
    }

    return found;
}

Upvotes: 0

Courage
Courage

Reputation: 792

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

Upvotes: 1

Related Questions