2

I'm trying to create a TreeView which displays directory contents such as:

ABC BCD 123.php 

Where ABC and BCD are both directories. I feel like I'm missing something as the TreeView works fine before I strip out the full directory location but once I strip it, it won't display like the above.

public void displayTreeView(String inputDirectoryLocation, CheckBoxTreeItem<String> mainRootItem) { // Creates the root item. CheckBoxTreeItem<String> rootItem = new CheckBoxTreeItem<>(inputDirectoryLocation); // Hides the root item of the tree view. treeView.setShowRoot(false); // Creates the cell factory. treeView.setCellFactory(CheckBoxTreeCell.<String>forTreeView()); // Get a list of files. File fileInputDirectoryLocation = new File(inputDirectoryLocation); File fileList[] = fileInputDirectoryLocation.listFiles(); // Loop through each file and directory in the fileList. for (int i = 0; i < fileList.length; i++) { // Check if fileList[i] is a file or a directory. if (fileList[i].isDirectory()) { // Re-iterate through as is directory. displayTreeView(fileList[i].toString(), rootItem); } else { // Check the file type of the file. String fileType = Util.retrieveFileType(fileList[i].toString()); // Check if the file type is the same file type we are searching for. In the future we just add the or symbol to support other file types. if (fileType.equals(".php")) { // Creates the item. CheckBoxTreeItem<String> fileCheckBoxTreeItem = new CheckBoxTreeItem<>(fileList[i].getName()); // Adds to the treeview. rootItem.getChildren().add(fileCheckBoxTreeItem); } } } // Check if the mainRootItem has been specified. if (mainRootItem == null) { // Sets the tree view root item. treeView.setRoot(rootItem); } else { // Creates the root item. CheckBoxTreeItem<String> dirCheckBoxTreeItem = new CheckBoxTreeItem<>(fileInputDirectoryLocation.getName()); // Sets the sub-root item. mainRootItem.getChildren().add(dirCheckBoxTreeItem); } } 

2 Answers 2

5

By combining the initialisation of the TreeView and a recursive method for constructing the tree you created messy code.

Better create a new method just for creating the tree:

public static void createTree(File file, CheckBoxTreeItem<String> parent) { if (file.isDirectory()) { CheckBoxTreeItem<String> treeItem = new CheckBoxTreeItem<>(file.getName()); parent.getChildren().add(treeItem); for (File f : file.listFiles()) { createTree(f, treeItem); } } else if (".php".equals(Util.retrieveFileType(file.toString()))) { parent.getChildren().add(new CheckBoxTreeItem<>(file.getName())); } } 

and use it in your displayTreeView method

public void displayTreeView(String inputDirectoryLocation) { // Creates the root item. CheckBoxTreeItem<String> rootItem = new CheckBoxTreeItem<>(inputDirectoryLocation); // Hides the root item of the tree view. treeView.setShowRoot(false); // Creates the cell factory. treeView.setCellFactory(CheckBoxTreeCell.<String>forTreeView()); // Get a list of files. File fileInputDirectoryLocation = new File(inputDirectoryLocation); File fileList[] = fileInputDirectoryLocation.listFiles(); // create tree for (File file : fileList) { createTree(file, rootItem); } treeView.setRoot(rootItem); } 

BTW: Your issue is caused by creating the tree structure and ignoring it for every node but the root (for non-root items the only node added to rootItem; for items other than the root you add is the "flat" dirCheckBoxTreeItem to the parent instead).

Sign up to request clarification or add additional context in comments.

Comments

4

Sorry for bumping an old question but I ran into a problem on implementing fabian's answer and I think this might be useful.

Browsing a large directory (e.g. root) can cause a performance issue. I resolved it by making it continue the recursive only after TreeItem is expanded.

private void createTree(File root_file, TreeItem parent) { if (root_file.isDirectory()) { TreeItem node = new TreeItem(root_file.getName()); parent.getChildren().add(node); for (File f: root_file.listFiles()) { TreeItem placeholder = new TreeItem(); // Add TreeItem to make parent expandable even it has no child yet. node.getChildren().add(placeholder); // When parent is expanded continue the recursive node.addEventHandler(TreeItem.branchExpandedEvent(), new EventHandler() { @Override public void handle(Event event) { createTree(f, node); // Continue the recursive as usual node.getChildren().remove(placeholder); // Remove placeholder node.removeEventHandler(TreeItem.branchExpandedEvent(), this); // Remove event } }); } } else { parent.getChildren().add(new TreeItem(root_file.getName())); } } 

Apart from modifying the for loop. I used TreeItem instead of CheckBoxTreeItem and some variable name, the rest is the same.


I also ran into another problem with Windows folder/files which's read-only or protected such as $RECYCLE.BIN and System Volume Information. I resolved the issue by checking if the file is system file or hidden or read-only or not. If yes ignore that file/folder.

try { DosFileAttributes attr = Files.readAttributes(root_file.toPath(), DosFileAttributes.class); if(attr.isSystem() || attr.isHidden() || attr.isReadOnly()) { // Do nothing } else { ... } } catch (IOException ex) { Logger.getLogger(FXMLMainController.class.getName()).log(Level.SEVERE, null, ex); } 

More info about checking file attributes

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.