配置扫描Local fie系统的TreeView仅包含具有文件类型的文件夹 [英] Configuring a TreeView which scans Local fie system to only include folders which have a file type

查看:337
本文介绍了配置扫描Local fie系统的TreeView仅包含具有文件类型的文件夹的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好吧所以我使用了这个网站的第二块代码

解决方案

您可以递归地创建树结构。有各种机制(请注意jewelsea对你的问题的评论),这里有一个:

  import java.io.IOException; 
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Comparator;
import java.util.function.Function;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

公共类FolderTreeView扩展Application {

private static final String ROOT_FOLDER =c:/ music; // TODO:更改或make selectable

@Override
public void start(Stage primaryStage)throws IOException {

// create root
TreeItem<路径> treeItem = new TreeItem< Path>(Paths.get(ROOT_FOLDER));
treeItem.setExpanded(true);

//创建树结构
createTree(treeItem);

//按名称排序树结构
treeItem.getChildren()。sort(Comparator.comparing(new Function< TreeItem< Path>,String>(){
@Override
public String apply(TreeItem< Path> t){
return t.getValue()。toString()。toLowerCase();
}
}));;

//创建组件
TreeView< Path> treeView = new TreeView< Path>(treeItem);
StackPane root = new StackPane();
root.getChildren()。add(treeView);
primaryStage.setScene(new Scene(root,1024,768));
primaryStage.setTitle(文件夹树视图示例);
primaryStage.show();

}

/ **
*递归创建树
* @param rootItem
* @throws IOException
* /
public static void createTree(TreeItem< Path> rootItem)抛出IOException {

try(DirectoryStream< Path> directoryStream = Files.newDirectoryStream(rootItem.getValue())){

for(Path path:directoryStream){

TreeItem< Path> newItem = new TreeItem< Path>(path);
newItem.setExpanded(true);

rootItem.getChildren()。add(newItem);

if(Files.isDirectory(path)){
createTree(newItem);
}
}
}
}


public static void main(String [] args){
launch(args) );
}
}

然后你有一棵树上有你的所有文件。由于您打算从给定的根路径扫描整个树结构并将其保留在内存中,因此您也可以简单地过滤树。我在这篇文章中获取了上面的代码和rli的答案中的过滤器代码适应它。它基本上是从原始结构创建一个过滤树结构。



这是完整的示例代码:

  import java.io.IOException; 
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Comparator;
import java.util.function.Function;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class FolderTreeViewWithFilter extends Application {

private static final String ROOT_FOLDER =c:/ music; // TODO:更改或选择

TreeItem< FilePath> rootTreeItem;
TreeView< FilePath>树视图;

@Override
public void start(Stage primaryStage)throws IOException {

// root component
VBox root = new VBox();

//过滤
TextField filter = new TextField();
filter.textProperty()。addListener((observable,oldValue,newValue) - > filterChanged(newValue));

// treeview
treeView = new TreeView< FilePath>();
VBox.setVgrow(treeView,Priority.ALWAYS);

root.getChildren()。addAll(filter,treeView);

// stage
primaryStage.setScene(new Scene(root,1024,768));
primaryStage.setTitle(带过滤器示例的文件夹树视图);
primaryStage.show();

//创建树
createTree();

//在树视图中显示树结构
treeView.setRoot(rootTreeItem);
}

/ **
*创建原始树结构
* @throws IOException
* /
private void createTree()抛出IOException {

//创建root
rootTreeItem = createTreeRoot();

//递归创建树结构
createTree(rootTreeItem);

//按名称排序树结构
rootTreeItem.getChildren()。sort(Comparator.comparing(new Function< TreeItem< FilePath>,String>(){
@Override
public String apply(TreeItem< FilePath> t){
return t.getValue()。toString()。toLowerCase();
}
}));;

}

/ **
*遍历目录结构并创建文件树
* @param rootItem
* @throws IOException
* /
public static void createTree(TreeItem< FilePath> rootItem)抛出IOException {

try(DirectoryStream< Path> directoryStream = Files.newDirectoryStream(rootItem.getValue() .getPath())){

for(Path path:directoryStream){

TreeItem< FilePath> newItem = new TreeItem< FilePath>(new FilePath(path));
newItem.setExpanded(true);

rootItem.getChildren()。add(newItem);

if(Files.isDirectory(path)){
createTree(newItem);
}
}
}
//捕获异常,e。 G。 java.nio.file.AccessDeniedException:c:\ System Volume Information,c:\ $ RECYCLE.BIN
catch(exception ex){
ex.printStackTrace();
}
}

/ **
*创建新的过滤树结构
* @param root
* @param filter
* @param filteredRoot
* /
private void filter(TreeItem< FilePath> root,String filter,TreeItem< FilePath> filteredRoot){

for(TreeItem< FilePath> child :root.getChildren()){

TreeItem< FilePath> filteredChild = new TreeItem<>(child.getValue());
filteredChild.setExpanded(true);

filter(child,filter,filteredChild);

if(!filteredChild.getChildren()。isEmpty()|| isMatch(filteredChild.getValue(),filter)){
filteredRoot.getChildren()。add(filteredChild);
}

}
}

/ **
*树过滤器的比较器
* @param值
* @param filter
* @return
* /
private boolean isMatch(FilePath value,String filter){
return value.toString()。toLowerCase()。contains( filter.toLowerCase()); // TODO:优化或更改(检查文件扩展名等)
}

/ **
*根据过滤器显示原始树或过滤树
* @ param filter
* /
private void filterChanged(String filter){
if(filter.isEmpty()){
treeView.setRoot(rootTreeItem);
}
else {
TreeItem< FilePath> filteredRoot = createTreeRoot();
filter(rootTreeItem,filter,filteredRoot);
treeView.setRoot(filteredRoot);
}
}

/ **
*创建根节点。用于原始树和过滤树。
*另一种选择是克隆根。
* @return
* /
private TreeItem< FilePath> createTreeRoot(){
TreeItem< FilePath> root = new TreeItem< FilePath>(new FilePath(Paths.get(ROOT_FOLDER)));
root.setExpanded(true);
返回root;
}

/ **
*包含overwritte toString方法的路径的包装器。我们只想将最后一个路径部分看作树节点,而不是整个路径。
* /
私有静态类FilePath {

路径路径;
字符串文字;

public FilePath(路径路径){

this.path = path;

//显示文本:最后一个路径部分
//考虑root,e。 G。 c:\
if(path.getNameCount()== 0){
this.text = path.toString();
}
//考虑文件夹结构
else {
this.text = path.getName(path.getNameCount() - 1).toString();
}

}

public Path getPath(){
return path;
}

public String toString(){

//提示:如果你想查看整个路径,请使用:
/ / return path.toString();

//仅显示最后一个路径部分
返回文本;

}
}

public static void main(String [] args){
launch(args);
}
}

只需在文本字段中输入搜索文本,即树将相应地进行过滤。



如果您想查看完整路径,可以更改toString()方法。此外,当前搜索子字符串而不是文件扩展名。这只是为了演示,根据您的需要调整它是微不足道的。



如果您想在另一个树视图或列表视图中显示树的部分,则会应用类似的机制。



示例如果您希望获得包含带有e的文件的所有节点的树结构。 G。文本过滤器中的子串mp3,而不是在树中显示文件本身,这里是过滤方法的修改版本:

  / ** 
*创建新的过滤树结构
* @param root
* @param filter
* @param filteredRoot
* /
private void filter(TreeItem< FilePath> root,String filter,TreeItem< FilePath> filteredRoot){

for(TreeItem< FilePath> child:root.getChildren()){

TreeItem< ;文件路径> filteredChild = new TreeItem<>(child.getValue());
filteredChild.setExpanded(true);

filter(child,filter,filteredChild);

boolean hasItem = false;
for(TreeItem< FilePath> subChild:child.getChildren()){
if(isMatch(subChild.getValue(),filter)){
hasItem = true;
休息;
}
}

if(!filteredChild.getChildren()。isEmpty()|| hasItem){
filteredRoot.getChildren()。add(filteredChild);
}

}
}

如果你我希望以执行/内存效率的方式做到这一点,你可以看看 TreeItem 示例代码,只有在您导航到文件夹时才会扫描文件夹。


Okay so I used the second block of code from this website http://www.java2s.com/Tutorials/Java/JavaFX/0660__JavaFX_Tree_View.htm where it states "The following code create a dynamic tree from the local file system"

I do not understand how this code works in order to customise it to my needs. Particularly the overriding methods, there did not seem to be a place where I could add in "only add folders down to the sub directory which contain mp3 files". I reckon it's likely going to require something more complex such as something that goes through and removes folders. I'm honestly not sure.

I have tried to use this code in my program which is to show mp3 files. The idea was to have two treeViews side by side, the left side shows the hierarchy of folders to the folders which have mp3 files in them (and do not shows other folders which do not have mp3 files in them) and the right side shows files which are of only mp3 file type in those folders. There is a screenshot further down.

This is the code I have so far which returns a TreeView in a VBox. There are two segments of code which are commented out. The first is due to the fact that java: search file according to its name in directory and subdirectories does not wish to search my C: drive. (I do not know why). So I changed it to only scan my D: (Partition drive). The second is from the webpage where I got the main segment of code. This code was moved to an outer class which handles. As well as a cheeky bit of code to handle more than one drive.

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.VBox;
import org.apache.commons.io.FileUtils;

/**
 * https://stackoverflow.com/questions/6251762/java-search-file-according-to-its-name-in-directory-and-subdirectories
 * https://stackoverflow.com/questions/26690247/how-to-make-directories-expandable-in-javafx-treeview
 * http://www.java2s.com/Tutorials/Java/JavaFX/0660__JavaFX_Tree_View.htm
 *
 * @author Scorchgid
 */
public class FolderTreeView {

    int x = 0;
    private final String fileName = ".mp3";
    private MainView mainView;
    private TreeView<File> treeViewFile = new TreeView<>();

    public TreeView<File> getTreeViewFile() {
        return treeViewFile;
    }

    public void setTreeViewFile(TreeView<File> treeViewFile) {
        this.treeViewFile = treeViewFile;
    }

    public VBox treeStack() throws IOException {
        VBox vbox = new VBox();
        File[] drives = File.listRoots();
        ArrayList<File> fileListing;
        /*for (File dir : drives) {
            System.out.println(dir.toString());
            fileListing = restrictingList(dir);
        }*/
        fileListing = restrictingList(new File("D:\\"));

        ArrayList<TreeItem> treeItems = new ArrayList<>();
        for (File dir : drives) {
            //System.out.println(dir.toString());
            treeItems.add(createNode(dir));
        }
        TreeView<File> tree = proxyCreateNode(treeItems);
        vbox.getChildren().add(tree);

        return vbox;
    }

    // https://stackoverflow.com/questions/22260032/set-two-root-nodes-for-treeview
    public TreeView<File> proxyCreateNode(ArrayList<TreeItem> arrayListTreeItem) {
        TreeItem<File> proxyItem = new TreeItem<>();
        proxyItem.setExpanded(true);
        for (TreeItem<File> item : arrayListTreeItem) {
            proxyItem.getChildren().addAll(item);
        }
        TreeView<File> tree = new TreeView<>(proxyItem);
        tree.setShowRoot(false);
        return tree;
    }

    private ArrayList<File> restrictingList(File root) {
        ArrayList<File> fileArray = new ArrayList<>();        
        boolean recursive = true;        
        Collection files = FileUtils.listFiles(root, null, recursive);
        for (Iterator iterator = files.iterator(); iterator.hasNext();) {
            File file = (File) iterator.next();
            if (file.getName().endsWith(fileName)) {
                fileArray.add(file);              
            }
        }
        return fileArray;
    }

    /*    @Override
     public void start(Stage stage) {
     Scene scene = new Scene(new Group(), 300, 300);

     TreeItem<File> root = createNode(new File("c:/"));
     TreeView treeView = new TreeView<File>(root);

     vbox.getChildren().add(treeView);
     ((Group) scene.getRoot()).getChildren().add(vbox);

     stage.setScene(scene);
     stage.show();
     }
     */
    private TreeItem<File> createNode(final File f) {
        return new TreeItem<File>(f) {
            private boolean isLeaf;
            private boolean isFirstTimeChildren = true;
            private boolean isFirstTimeLeaf = true;

            @Override
            public ObservableList<TreeItem<File>> getChildren() {
                if (isFirstTimeChildren) {
                    isFirstTimeChildren = false;
                    super.getChildren().setAll(buildChildren(this));
                }
                return super.getChildren();
            }

            @Override
            public boolean isLeaf() {
                if (isFirstTimeLeaf) {
                    isFirstTimeLeaf = false;
                    File f = (File) getValue();
                    isLeaf = f.isFile();
                }
                return isLeaf;
            }

            private ObservableList<TreeItem<File>> buildChildren(
                    TreeItem<File> TreeItem) {
                File f = TreeItem.getValue();
                if (f == null) {
                    return FXCollections.emptyObservableList();
                }
                if (f.isFile()) {
                    return FXCollections.emptyObservableList();
                }
                File[] files = f.listFiles();
                if (files != null) {
                    ObservableList<TreeItem<File>> children = FXCollections
                            .observableArrayList();
                    for (File childFile : files) {
                        //System.out.println("Adding " + childFile.getAbsolutePath());
                        if (childFile.isDirectory()) {
                            children.add(createNode(childFile));
                        }
                    }
                    return children;
                }
                return FXCollections.emptyObservableList();
            }
        };
    }
}

解决方案

You can create the tree structure recursively. There are various mechanisms (please also note jewelsea's comment to your question), here's one:

import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Comparator;
import java.util.function.Function;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class FolderTreeView extends Application {

    private static final String ROOT_FOLDER = "c:/music"; // TODO: change or make selectable

    @Override
    public void start(Stage primaryStage) throws IOException {

        // create root
        TreeItem<Path> treeItem = new TreeItem<Path>(Paths.get( ROOT_FOLDER));
        treeItem.setExpanded(true);

        // create tree structure
        createTree( treeItem);

        // sort tree structure by name
        treeItem.getChildren().sort( Comparator.comparing( new Function<TreeItem<Path>, String>() {
            @Override
            public String apply(TreeItem<Path> t) {
                return t.getValue().toString().toLowerCase();
            }
        }));

        // create components
        TreeView<Path> treeView = new TreeView<Path>(treeItem);
        StackPane root = new StackPane();
        root.getChildren().add(treeView);
        primaryStage.setScene(new Scene(root, 1024, 768));
        primaryStage.setTitle("Folder Tree View Example");
        primaryStage.show();

    }

    /**
     * Recursively create the tree
     * @param rootItem
     * @throws IOException
     */
    public static void createTree(TreeItem<Path> rootItem) throws IOException {

        try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(rootItem.getValue())) {

            for (Path path : directoryStream) {

                TreeItem<Path> newItem = new TreeItem<Path>(path);
                newItem.setExpanded(true);

                rootItem.getChildren().add(newItem);

                if (Files.isDirectory(path)) {
                    createTree(newItem);
                }
            }
        }
    }


    public static void main(String[] args) {
        launch(args);
    }
}

Then you have a tree with all of your files. Since you intend to scan the entire tree structure from a given root path and keep it in memory, you may as well simply filter the tree. I took the code above and the filter code from rli's answer in this post and adapted it. It basically creates a filtered tree structure from the original structure.

Here's the full example code:

import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Comparator;
import java.util.function.Function;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class FolderTreeViewWithFilter extends Application {

    private static final String ROOT_FOLDER = "c:/music"; // TODO: change or make selectable

    TreeItem<FilePath> rootTreeItem;
    TreeView<FilePath> treeView;

    @Override
    public void start(Stage primaryStage) throws IOException {

        // root component
        VBox root = new VBox();

        // filter
        TextField filter = new TextField();
        filter.textProperty().addListener((observable, oldValue, newValue) -> filterChanged(newValue));

        // treeview
        treeView = new TreeView<FilePath>();
        VBox.setVgrow(treeView, Priority.ALWAYS);

        root.getChildren().addAll( filter, treeView);

        // stage
        primaryStage.setScene(new Scene(root, 1024, 768));
        primaryStage.setTitle("Folder Tree View With Filter Example");
        primaryStage.show();

        // create tree
        createTree();

        // show tree structure in tree view
        treeView.setRoot(rootTreeItem);
    }

    /**
     * Create original tree structure
     * @throws IOException
     */
    private void createTree() throws IOException {

        // create root
        rootTreeItem = createTreeRoot();

        // create tree structure recursively
        createTree( rootTreeItem);

        // sort tree structure by name
        rootTreeItem.getChildren().sort( Comparator.comparing( new Function<TreeItem<FilePath>, String>() {
            @Override
            public String apply(TreeItem<FilePath> t) {
                return t.getValue().toString().toLowerCase();
            }
        }));

    }

    /**
     * Iterate through the directory structure and create a file tree
     * @param rootItem
     * @throws IOException
     */
    public static void createTree(TreeItem<FilePath> rootItem) throws IOException {

        try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(rootItem.getValue().getPath())) {

            for (Path path : directoryStream) {

                TreeItem<FilePath> newItem = new TreeItem<FilePath>( new FilePath( path));
                newItem.setExpanded(true);

                rootItem.getChildren().add(newItem);

                if (Files.isDirectory(path)) {
                    createTree(newItem);
                }
            }
        }
        // catch exceptions, e. g. java.nio.file.AccessDeniedException: c:\System Volume Information, c:\$RECYCLE.BIN
        catch( Exception ex) {
            ex.printStackTrace();
        }
    }

    /**
     * Create new filtered tree structure
     * @param root
     * @param filter
     * @param filteredRoot
     */
    private void filter(TreeItem<FilePath> root, String filter, TreeItem<FilePath> filteredRoot) {

        for (TreeItem<FilePath> child : root.getChildren()) {

            TreeItem<FilePath> filteredChild = new TreeItem<>( child.getValue());
            filteredChild.setExpanded(true);

            filter(child, filter, filteredChild );

            if (!filteredChild.getChildren().isEmpty() || isMatch(filteredChild.getValue(), filter)) {
                filteredRoot.getChildren().add(filteredChild);
            }

        }
    }

    /**
     * Comparator for tree filter
     * @param value
     * @param filter
     * @return
     */
    private boolean isMatch(FilePath value, String filter) {
        return value.toString().toLowerCase().contains( filter.toLowerCase()); // TODO: optimize or change (check file extension, etc)
    }

    /**
     * Show original tree or filtered tree depending on filter
     * @param filter
     */
    private void filterChanged(String filter) {
        if (filter.isEmpty()) {
            treeView.setRoot(rootTreeItem);
        }
        else {
            TreeItem<FilePath> filteredRoot = createTreeRoot();
            filter(rootTreeItem, filter, filteredRoot);
            treeView.setRoot(filteredRoot);
        }
    }

    /**
     * Create root node. Used for the original tree and the filtered tree.
     * Another option would be to clone the root.
     * @return
     */
    private TreeItem<FilePath> createTreeRoot() {
        TreeItem<FilePath> root = new TreeItem<FilePath>( new FilePath( Paths.get( ROOT_FOLDER)));
        root.setExpanded(true);
        return root;
    }

    /**
     * Wrapper for the path with overwritte toString method. We only want to see the last path part as tree node, not the entire path.
     */
    private static class FilePath {

        Path path;
        String text;

        public FilePath( Path path) {

            this.path = path;

            // display text: the last path part
            // consider root, e. g. c:\
            if( path.getNameCount() == 0) {
                this.text = path.toString();
            }
            // consider folder structure
            else {
                this.text = path.getName( path.getNameCount() - 1).toString();
            }

        }

        public Path getPath() {
            return path;
        }

        public String toString() {

            // hint: if you'd like to see the entire path, use this:
            // return path.toString();

            // show only last path part
            return text;

        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}

Simply enter search text in the text field, the tree will be filtered accordingly.

You may change the toString() method if you'd like to see the full path. Also, currently a substring is searched instead of the file extension. That's just for demo, adapting it for your needs is trivial.

Similar mechanism applies if you'd like to display parts of the tree in another tree view or list view.

Example if you'd like to get a tree structure with all nodes that contain a file with e. g. substring "mp3" in the text filter while not displaying the file itself in the tree, here's the modified version of the filter method:

/**
 * Create new filtered tree structure
 * @param root
 * @param filter
 * @param filteredRoot
 */
private void filter(TreeItem<FilePath> root, String filter, TreeItem<FilePath> filteredRoot) {

    for (TreeItem<FilePath> child : root.getChildren()) {

        TreeItem<FilePath> filteredChild = new TreeItem<>( child.getValue());
        filteredChild.setExpanded(true);

        filter(child, filter, filteredChild );

        boolean hasItem = false;
        for (TreeItem<FilePath> subChild: child.getChildren()) {
            if( isMatch( subChild.getValue(), filter)) {
                hasItem = true;
                break;
            }
        }

        if (!filteredChild.getChildren().isEmpty() || hasItem) {
            filteredRoot.getChildren().add(filteredChild);
        }

    }
}

If you'd like to do it the performing / memory efficient way, you could take a look at the TreeItem example code which will scan a folder only when you navigate into it.

这篇关于配置扫描Local fie系统的TreeView仅包含具有文件类型的文件夹的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆