JavaFX зависает при поиске

268
07 апреля 2022, 11:50

У меня в программе есть рекурсивный поиск и открытие файла, в обоих случаях программа зависает на время обработки, я пытался решить эту проблему, но оно по прежнему зависает. Вот мои варианты решения этот проблемы

      private void initialize() {
        //TODO
        treeView = new FileSystemTree();
        Config.setInWord(true);
        checkInWord.setOnAction(actionEvent -> Config.setInWord(checkInWord.isSelected()));
        //Event Button Search
        btnFind.setOnAction(event -> {
            newFind();
            if (Config.isRoot()) {
                String finalSFilterExt = filterExt.getText();
                String finalSearchW = searchWord.getText();
                // Update the Label on the JavaFx Application Thread
                Platform.runLater(new Runnable()
                {
                    @SneakyThrows
                    @Override
                    public void run()
                    {
                        fileView.setRoot(treeView.filterChanged(finalSFilterExt, finalSearchW));
                    }
                });
  /*              new Thread(new Runnable() {
                    public void run() {
                        Platform.runLater(() -> {
                            try {
                                fileView.setRoot(treeView.filterChanged(finalSFilterExt, finalSearchW));
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        });
                    }
                }).start();*/
                /*CompletableFuture.runAsync(() -> {
                    try {
                        fileView.setRoot(treeView.filterChanged(finalSFilterExt, finalSearchW));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                });*/
            }
        });

Каждый из способов, не дал нужного результата, приложение виснет.

Класс для генерации дерева(во время поиска)

class FileSystemTree {
    @Getter
    @Setter
    String rootFolder = ""; // TODO: change or make selectable
    private TreeView<File> treeView;
    private TreeItem<File> rootTreeItem;

    FileSystemTree() {
        treeView = new TreeView<File>();
    }
    FileSystemTree(String root) throws IOException {
        this();
        rootFolder = root;
        createTree();
    }
    void createTree() throws IOException {
        // create tree structure recursively
        rootTreeItem = createTreeRoot();
        treeView.setRoot(rootTreeItem);
        createTree(rootTreeItem);
        // sort tree structure by name
        rootTreeItem.getChildren().sort(Comparator.comparing(new Function<TreeItem<File>, String>() {
            @Override
            public String apply(TreeItem<File> t) {
                return t.getValue().toString().toLowerCase();
            }
        }));
    }
    public static void createTree(TreeItem<File> rootItem) throws IOException {

        //TODO check it later
        try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(Paths.get(rootItem.getValue().getPath()))) {
            for (Path path : directoryStream) {
                TreeItem<File> newItem = new TreeItem<>(new File(String.valueOf(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();
        }
    }
    private void filter(TreeItem<File> root, String filter, TreeItem<File> filteredRoot, String searchString) throws IOException {
        for (TreeItem<File> child : root.getChildren()) {
            TreeItem<File> filteredChild = new TreeItem<>(child.getValue());
            filteredChild.setExpanded(true);
            filter(child, filter, filteredChild, searchString);
            if (!filteredChild.getChildren().isEmpty()) {
                filteredRoot.getChildren().add(filteredChild);
            }
            //TODO reformat
            if (isMatch(filteredChild.getValue(), filter)) {
                if (Myr.run(searchString, Paths.get(filteredChild.getValue().getPath())).isFound())
                    filteredRoot.getChildren().add(filteredChild);
            }
        }
    }
    private boolean isMatch(File value, String filter) {
        //    return value.toString().toLowerCase().endsWith(filter.toLowerCase()); // TODO: optimize or change (check file extension, etc)
        boolean b = value.toString().toLowerCase().endsWith(filter.toLowerCase());
        if (b)
            System.out.println("Найден файл: " + value.getAbsolutePath() + " Filter: " + filter);
        return b;
    }
/*    Task<String> task = new Task<String>() {
        @Override
        protected String call() throws Exception {
            if (filterExt.isEmpty()) {
                treeView.setRoot(rootTreeItem);
            } else {
                TreeItem<File> filteredRoot = createTreeRoot();
                filter(rootTreeItem, filterExt, filteredRoot, searchWord);
                treeView.setRoot(filteredRoot);
            }
            return treeView.getRoot();
        }
    };*/
    TreeItem<File> filterChanged(String filterExt, String searchWord) throws IOException {
        if (filterExt.isEmpty()) {
            treeView.setRoot(rootTreeItem);
        } else {
            TreeItem<File> filteredRoot = createTreeRoot();
            filter(rootTreeItem, filterExt, filteredRoot, searchWord);
            treeView.setRoot(filteredRoot);
        }
        return treeView.getRoot();
    }
    private TreeItem<File> createTreeRoot() {
        TreeItem<File> root = new TreeItem<>(new File(rootFolder));
        root.setExpanded(true);
        return root;
    }

}

Как бы не пытался распаралелить, всё равно виснет основной поток. Также я пытался решить эту задачу с помощью Task`ов, но у меня не получилось. И у меня из-за не знания были проблемы с получением аргументов в task и получением результата из неё

Answer 1

Все тяжелые операции нужно выполнять в фоновых потоках и результат уже передавать в главный. Иначе, естественно будет виснуть.

new Thread(() -> {
    // Тут выполняем всё тяжелое
    Platform.runLater(() -> {
        // Тут выводим результат в интерфейс
    });
}).start();
READ ALSO
Структура папок в Spring MVC

Структура папок в Spring MVC

Есть ли какое то правило для строгого именования папок в Spring MVCсмотрел разные видео где использовали например папку dao, я так понимаю она нужна...

204
Подсказки css-свойств/значений для sass в VS Code

Подсказки css-свойств/значений для sass в VS Code

Работаю в VS Code, пишу стили в *sass и не показываются подсказки как в файлах *

121
MySQL возвращает ASCII, а должен UTF-8 PHP

MySQL возвращает ASCII, а должен UTF-8 PHP

На локальном хосте такого нету: запрос->ответ в виде массива с кодировкой UTF-8Но когда закинул на byet host, все кириллические символы превратились...

241
Принцип DIP из SOLID и Autowiring из DI-контейнеров

Принцип DIP из SOLID и Autowiring из DI-контейнеров

Принцип DIP гласит: зависимости должны быть на абстракциях, а не от конкретной реализации

121