Java 使用texfield搜索/过滤树视图

Java 使用texfield搜索/过滤树视图,java,javafx,treeview,Java,Javafx,Treeview,我一直试图找到一个答案,但这似乎是一个地狱般的复杂做 我想做的是,我有一个树视图和一个文本字段,我想能够搜索,所以只有树视图中的树项匹配文本字段上显示的内容 例如,如果有人在文本字段中写入“lat”,则树视图会显示“latency”、“latio”等文件夹 treeview填充代码如下所示 @FXML private void fillTreeView() { // The tree needs a root, and it needs to be a DocumentObject

我一直试图找到一个答案,但这似乎是一个地狱般的复杂做

我想做的是,我有一个树视图和一个文本字段,我想能够搜索,所以只有树视图中的树项匹配文本字段上显示的内容

例如,如果有人在文本字段中写入“lat”,则树视图会显示“latency”、“latio”等文件夹

treeview填充代码如下所示

@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);
}
@FXML
私有void fillTreeView(){
//树需要一个根,它需要一个DocumentObject
//所以我们创建一个空文件夹并隐藏它
TreeItem>folderNode=新的TreeItem(文件夹);
对于(文件引用文件:folder.getFileList()){

TreeItem如果您只筛选根节点的直接子节点,那么它相当简单。只需将顶级节点保留在一个单独的
可观察列表
,在其周围包装一个
过滤器列表
,然后使用
绑定.bindContent()
以确保根节点的子节点列表包含与
过滤器数据列表相同的元素

假设您的
DocumentObject
有一个方法,比如说
getName()
,它返回要对其应用筛选器的文本,并且您有一个名为
TextField
TextField
,用户在其中键入筛选器文本,这看起来像:

@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);
}
@FXML
私有void fillTreeView(){
//树需要一个根,它需要一个DocumentObject
//所以我们创建一个空文件夹并隐藏它
TreeItem>>firstLevel=FXCollections.observableArrayList();
对于(文件夹:logic.getFolderList()){
TreeItem>fileNode=新的TreeItem(文件);
folderNode.getChildren().add(fileNode);
}
添加(folderNode);
}
treeRoot.setExpanded(true);

FilteredList如果您只筛选根节点的直接子节点,这相当简单。只需将顶级节点保留在一个单独的
ObservableList
中,在其周围包装一个
FilteredList
,然后使用
Bindings.bindContent()
以确保根节点的子节点列表包含与
过滤器数据列表相同的元素

假设您的
DocumentObject
有一个方法,比如说
getName()
,它返回要对其应用筛选器的文本,并且您有一个名为
TextField
TextField
,用户在其中键入筛选器文本,这看起来像:

@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);
}
@FXML
私有void fillTreeView(){
//树需要一个根,它需要一个DocumentObject
//所以我们创建一个空文件夹并隐藏它
TreeItem>>firstLevel=FXCollections.observableArrayList();
对于(文件夹:logic.getFolderList()){
TreeItem>fileNode=新的TreeItem(文件);
folderNode.getChildren().add(fileNode);
}
添加(folderNode);
}
treeRoot.setExpanded(true);


FilteredList一些代码会很好。@Sedrick补充了treeview是如何构建的。但是我甚至不知道如何开始搜索/过滤它,因为你的
树总是只有两个深?我将试着看看我是否能拿出一个示例应用程序。你只是在一个级别上过滤吗?(即,只是过滤根节点的直接子节点?)如果是这样的话,那还不算太糟。或者你想过滤整个树:那更复杂。一些代码会很棒。@Sedrick补充了treeview是如何构建的。但是我甚至不知道我们该如何开始搜索/过滤它,因为你的
树总是只有两层深?我将试着看看我是否能想出一个示例应用程序。你只是过滤吗在一个级别上?(即仅过滤根节点的直接子节点?)如果是这样,这还不算太糟。或者您想过滤整个树:这更复杂。您可能知道kware.net/?p=204…这是一种工作方式,尽管脏(反射性地用filteredList替换内部子列表)@kleopatra,该类有一个不使用反射的更新版本。他在注释部分的底部提到了它。@wcmatthysen没有意识到更新,感谢指针:)我无法多次启动此筛选器。我没有使用textfield的属性,只是维护一个SimpleObject属性在类中。当我通过set()更新属性的值时,筛选器似乎不会再次启动。您可能知道kware.net/?p=204…这是一种虽然脏但仍能正常工作的方法(反射性地将内部子列表替换为filteredList)@kleopatra,该类有一个不使用反射的更新版本。他在注释部分的底部提到了它。@wcmatthysen没有意识到更新,感谢指针:)我无法多次启动此筛选器。我没有使用textfield的属性,只是维护一个SimpleObject属性当我通过set()更新属性的值时,过滤器似乎不会再次启动。