質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
JavaFX

JavaFXとは、Java仮想マシン上で動作するリッチインターネットアプリケーション (RIA) のGUIライブラリです。Swingとは異なり、FXMLと呼ばれる XMLとCSSを併用してデザインを記述します。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

1回答

1856閲覧

JavaFxのTreeViewにフォルダ ファイル(ディレクトリ)階層を表示したい。

d95

総合スコア0

JavaFX

JavaFXとは、Java仮想マシン上で動作するリッチインターネットアプリケーション (RIA) のGUIライブラリです。Swingとは異なり、FXMLと呼ばれる XMLとCSSを併用してデザインを記述します。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2020/04/24 21:00

編集2020/04/24 21:03

実現したいこと と 試したこと

JavaFxのTreeViewにフォルダ ファイル(ディレクトリ)階層を表示したいです。

Oracleの公式サイト(ドキュメント)にメモリーを消費しない効率的な方法が紹介されていたので、テスト①のように作りました。
「フォルダを展開した時にその子フォルダのみを設定している」ということが標準出力で調べて分かりました(詳しいことは不明)(効率的ですね)。

しかし、要素全てがフルパスで表示されてしまって見ずらい(画像添付)ので改良したいと思いました。
そこでjava.io.Fileを自作クラスFileExに置き換えて、テスト②のように改良してみました。

しかし、ルートフォルダが空文字になってしまったり、ファイルが表示されないので困っています。

教えて頂きたいこと

以下について、できるだけ教えて頂きたいです。(全てではなくても有難いです。)
・TreeItem と TreeCell の違いや役割について。
・テスト②について、無駄な部分間違い他のアプローチについて
・選択されたフォルダやファイルのフルパスを取得する方法(クリックイベントなどで)

宜しくお願い致します。

目指すところ

(理想なので分かることだけでも有難いです。)
・test.TestBrowser1.javaファイルのように再帰処理を使うなど、ソースコードが少なくて済むこと。
・大量のフォルダ ファイル があっても重くならないこと。

参考にしたサイト

https://qiita.com/sipadan2003/items/71ddbf0259ce89ba5243
https://qiita.com/sipadan2003/items/4b909a294b039b0bfd2f
https://qiita.com/sipadan2003/items/9305e6c1f52e8e0621d7
https://qiita.com/sipadan2003/items/d9afee2d6eb039f2b832

https://aoe-tk.hatenablog.com/entry/20131206/1386345344

http://krr.blog.shinobi.jp/javafx/javafx%20%E3%82%BB%E3%83%AB%E3%81%AE%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%9E%E3%82%A4%E3%82%BA

https://docs.oracle.com/javase/jp/8/javafx/api/
https://docs.oracle.com/javase/jp/8/javafx/api/javafx/scene/control/TreeItem.html

テスト①

以下のソースコードを参考にしました。
https://docs.oracle.com/javase/jp/8/javafx/api/javafx/scene/control/TreeItem.html

AppTopWindowController.javaファイル

java

1import java.net.URL; 2import java.util.ResourceBundle; 3 4import javafx.fxml.FXML; 5import javafx.scene.control.TreeView; 6import java.io.File; 7import test.TestBrowser1; 8 9public class AppTopWindowController { 10 @FXML private ResourceBundle resources; 11 @FXML private URL location; 12 @FXML private TreeView<File> folderTree; 13 14 @FXML 15 void initialize() { 16 TestBrowser1 testBrowser1 = new TestBrowser1(); 17 folderTree.setRoot(testBrowser1.buildFileSystemBrowser()); 18 } 19}

test.TestBrowser1.javaファイル

java

1package test; 2 3import java.io.File; 4 5import javafx.collections.FXCollections; 6import javafx.collections.ObservableList; 7import javafx.scene.control.TreeItem; 8 9//https://docs.oracle.com/javase/jp/8/javafx/api/javafx/scene/control/TreeItem.html を参考にしたもの。 10 11public class TestBrowser1 { 12 public TreeItem<File> buildFileSystemBrowser() { 13 TreeItem<File> root = createNode(new File("D:\"));//使用環境はwindowsなのでD:\となる。開発環境ではエスケープしてD:\とする。 14 return root; 15 } 16 17 // This method creates a TreeItem to represent the given File. It does this 18 // by overriding the TreeItem.getChildren() and TreeItem.isLeaf() methods 19 // anonymously, but this could be better abstracted by creating a 20 // 'FileTreeItem' subclass of TreeItem. However, this is left as an exercise 21 // for the reader. 22 private TreeItem<File> createNode(final File f) { 23 return new TreeItem<File>(f) { 24 // We cache whether the File is a leaf or not. A File is a leaf if 25 // it is not a directory and does not have any files contained within 26 // it. We cache this as isLeaf() is called often, and doing the 27 // actual check on File is expensive. 28 private boolean isLeaf; 29 30 // We do the children and leaf testing only once, and then set these 31 // booleans to false so that we do not check again during this 32 // run. A more complete implementation may need to handle more 33 // dynamic file system situations (such as where a folder has files 34 // added after the TreeView is shown). Again, this is left as an 35 // exercise for the reader. 36 private boolean isFirstTimeChildren = true; 37 private boolean isFirstTimeLeaf = true; 38 39 @Override public ObservableList<TreeItem<File>> getChildren() { 40 if (isFirstTimeChildren) { 41 isFirstTimeChildren = false; 42 43 // First getChildren() call, so we actually go off and 44 // determine the children of the File contained in this TreeItem. 45 super.getChildren().setAll(buildChildren(this)); 46 } 47 return super.getChildren(); 48 } 49 50 @Override public boolean isLeaf() { 51 if (isFirstTimeLeaf) { 52 isFirstTimeLeaf = false; 53 File f = (File) getValue(); 54 isLeaf = f.isFile(); 55 } 56 return isLeaf; 57 } 58 59 private ObservableList<TreeItem<File>> buildChildren(TreeItem<File> TreeItem) { 60 File f = TreeItem.getValue(); 61 if (f != null && f.isDirectory()) { 62 File[] files = f.listFiles(); 63 if (files != null) { 64 ObservableList<TreeItem<File>> children = FXCollections.observableArrayList(); 65 66 for (File childFile : files) { 67 if (childFile.isDirectory()){ 68 System.out.println(childFile.getName()); 69 children.add(createNode(childFile)); 70 } 71 } 72 73 return children; 74 } 75 } 76 return FXCollections.emptyObservableList(); 77 } 78 }; 79 } 80}

実行結果
イメージ説明

テスト②

AppTopWindowController.javaファイル (FXMLのコントローラー クラス)

java

1import java.net.URL; 2import java.util.ResourceBundle; 3 4import javafx.fxml.FXML; 5import javafx.scene.control.TreeView; 6import test.FileEx; //java.io.Fileとjava.io.File.getName()を保持するモデル。 7import test.TestBrowser2; 8 9public class AppTopWindowController { 10 @FXML private ResourceBundle resources; 11 @FXML private URL location; 12 @FXML private TreeView<FileEx> folderTree; 13 14 @FXML 15 void initialize() { 16 TestBrowser2 testBrowser2 = new TestBrowser2(); 17 TestBrowser2.buildFileSystemBrowser(folderTree); 18 } 19}

test.FileEx.javaファイル(java.io.Fileとjava.io.File.getName()を保持するモデル。)

java

1package test; 2 3import java.io.File; 4 5public class FileEx {//java.io.Fileとjava.io.File.getName()を保持するモデル。 6 private String name; 7 private File f; 8 9 FileEx(String name,File f){//コンストラクタ 10 this.name=name; 11 this.f=f; 12 } 13 14 String getName(){ 15 return this.name; 16 } 17 File getFile(){ 18 return this.f; 19 } 20}

test.FileTreeCell.javaファイル

java

1package test; 2 3import javafx.scene.control.TreeCell; 4 5public class FileTreeCell extends TreeCell<FileEx> { 6 //コンストラクタ 7 public FileTreeCell() { 8 //setText(""); 9 } 10 11 @Override 12 protected void updateItem(FileEx fileEx, boolean empty) { 13 super.updateItem(fileEx, empty); 14 if (empty) { 15 16 } else { 17 setText(fileEx.getName()); 18 } 19 } 20}

test.TestBrowser2.javaファイル

java

1package test; 2 3import java.io.File; 4 5import javafx.collections.FXCollections; 6import javafx.collections.ObservableList; 7import javafx.scene.control.TreeCell; 8import javafx.scene.control.TreeItem; 9import javafx.scene.control.TreeView; 10import javafx.util.Callback; 11 12//https://docs.oracle.com/javase/jp/8/javafx/api/javafx/scene/control/TreeItem.html を参考に改良。 13 14public class TestBrowser2{ 15 public void buildFileSystemBrowser(TreeView<FileEx> treeView) { 16 File rootFile =new File("D:\"); //使用環境はwindowsなのでD:\となる。開発環境ではエスケープしてD:\とする。 17 TreeItem<FileEx> root = createNode(new FileEx(rootFile.getName(),rootFile)); 18 19 treeView.setCellFactory(new Callback<TreeView<FileEx>, TreeCell<FileEx>>() { 20 @Override 21 public TreeCell<FileEx> call(TreeView<FileEx> treeView) { 22 return new FileTreeCell(); 23 } 24 }); 25 treeView.setRoot(root); 26 } 27 28 private TreeItem<FileEx> createNode(final FileEx f) { 29 return new TreeItem<FileEx>(f) { 30 private boolean isLeaf; 31 private boolean isFirstTimeChildren = true; 32 private boolean isFirstTimeLeaf = true; 33 34 @Override 35 public ObservableList<TreeItem<FileEx>> getChildren() { 36 if (isFirstTimeChildren) { 37 isFirstTimeChildren = false; 38 super.getChildren().setAll(buildChildren(this)); 39 } 40 return super.getChildren(); 41 } 42 43 @Override public boolean isLeaf() { 44 if (isFirstTimeLeaf) { 45 isFirstTimeLeaf = false; 46 File f = getValue().getFile(); 47 isLeaf = f.isFile(); 48 } 49 return isLeaf; 50 } 51 52 private ObservableList<TreeItem<FileEx>> buildChildren(TreeItem<FileEx> TreeItem) { 53 File f = TreeItem.getValue().getFile(); 54 if (f != null && f.isDirectory()) { 55 File[] files = f.listFiles(); 56 if (files != null) { 57 ObservableList<TreeItem<FileEx>> children = FXCollections.observableArrayList(); 58 for (File childFile : files) { 59 if (childFile.isDirectory()){ 60 System.out.println(childFile.getName()); 61 FileEx tempFileEx = new FileEx(childFile.getName(),childFile); 62 children.add(createNode(tempFileEx)); 63 } 64 } 65 return children; 66 } 67 } 68 return FXCollections.emptyObservableList(); 69 } 70 }; 71 } 72}

バージョン

Java 8

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

FileExクラス、FileTreeCellクラス、このあたりはなくても実装できますね。

test.TestBrowser1.javaファイルのように再帰処理を使うなど、ソースコードが少なくて済むこと。

ディレクトリを掘るので再帰したくなりますが、再帰して返してくれるメソッドもあります。

https://docs.oracle.com/javase/jp/8/docs/api/java/nio/file/Files.html#walk-java.nio.file.Path-java.nio.file.FileVisitOption...-

大量のフォルダ ファイル があっても重くならないこと。

これは、どうでしょうね。どの程度までを想定しているのかによるとおもいますけど...

java

1import javafx.application.Application; 2import javafx.scene.Scene; 3import javafx.scene.control.TreeCell; 4import javafx.scene.control.TreeItem; 5import javafx.scene.control.TreeView; 6import javafx.stage.Stage; 7 8import java.io.File; 9import java.nio.file.Files; 10import java.nio.file.Path; 11import java.nio.file.Paths; 12import java.util.stream.Collectors; 13 14public class xxFileTree { 15 public static void main(final String[] args) { 16 Application.launch(App.class, args); 17 } 18 19 // 20 public static class App extends Application { 21 @Override 22 public void start(final Stage primaryStage) throws Exception { 23 final TreeView<File> treeView = new TreeView<>(); 24 25 final Path rootPath = Paths.get("/xxx"); 26 27 final TreeItem<File>[] directories = new TreeItem[999]; 28 29 for (Path path : Files.walk(rootPath).sorted().collect(Collectors.toList())) { 30 final TreeItem item = new TreeItem(path.toFile()); 31 final TreeItem<File> directory = directories[path.getParent().getNameCount()]; 32 33 if (Files.isDirectory(path)) { 34 item.setExpanded(true); 35 directories[path.getNameCount()] = item; 36 } 37 38 if (directory != null) { 39 directory.getChildren().add(item); 40 } 41 } 42 43 treeView.setRoot(directories[rootPath.getNameCount()]); 44 45 // 46 treeView.setCellFactory(a -> 47 new TreeCell<File>() { 48 @Override 49 protected void updateItem(File file, boolean empty) { 50 super.updateItem(file, empty); 51 if (empty) { 52 setText(""); 53 } else { 54 setText(file.getName()); 55 } 56 } 57 } 58 ); 59 60 // 61 treeView.getSelectionModel().selectedItemProperty().addListener((ob, ov, nv) -> { 62 if (nv != null) { 63 System.out.println(String.format("select ... %s", nv.getValue().getAbsolutePath())); 64 } 65 }); 66 67 // 68 primaryStage.setScene(new Scene(treeView)); 69 primaryStage.show(); 70 } 71 } 72}

投稿2020/04/25 03:30

shiketa

総合スコア4061

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問