Java FXML ProgressBar не будет обновляться, пока вся работа не будет завершена - PullRequest
0 голосов
/ 01 мая 2018

Я пытаюсь узнать о Java FX, используя Scene Builder и NetBeans, портировав приложение Java из командной строки, и оно работает в основном. Однако ни индикатор выполнения, ни текстовая область не обновляются до тех пор, пока рабочий не будет завершен. Кнопка «Образы процесса» не указывает, что она была нажата, через 5 или более секунд курсор показывает, что приложение занято. Я начал проект с помощью NetBeans-> New Project-> JavaFX-> Java FXML Application. Мой код находится в файле контроллера.

Я узнал (спасибо, Google), что это нормальное поведение для такого рода графического интерфейса и что обновления должны быть в своих собственных потоках, а не в том, как создавать нужные мне потоки.

Я создал вложенный поток, просто чтобы увеличить индикатор выполнения, он не работал. Затем я создал вложенный поток для рабочего, который использовал поток прогресса, ничего не изменилось. Затем я вложил поток выполнения во вложенный рабочий, но все еще без изменений. Метод / поток работника управляет списком файлов, отфильтровывая их и отправляя правильные файлы по одному методу, который исправляет любые ошибки, которые могут быть найдены. Рабочий поток отвечает за обновление индикатора выполнения, за обновление текстовой области отвечает метод, который «исправляет» файлы.

Нажатие этой кнопки запускает обработку.

    @FXML
private void handleBtnProcessImagesClick(ActionEvent event) {
    btnProcess.setText("Processing");
    if (!sourceDirExists) {
        updateLog("Need valid source folder to process images.",
                WARNING);
        return;
    }
    sourceDir = new File(txtFldSourceFolder.getText());
    createDestFolder();
    //processFiles();
    ThreadProcessImages pf = new ThreadProcessImages();
    pf.run();
}

Главный рабочий

class ThreadProcessImages extends Thread {

    /**
 * manage the progress bar while calculations are running
 */
class ThreadProgress extends Thread {

    double progress = 0.0;
    double max = 1.0 - 0.0005;

    ThreadProgress(double progress) {
        this.progress = progress;
    }

    @Override
    public void run() {
        if (progress == 0.0) {
            progressBar.setStyle("-fx-accent: SKYBLUE;");
            progressBar.setProgress(0.0);
            System.out.println("Thread start.");
        } else if (progress >= max) {
            progressBar.setStyle("-fx-accent: SPRINGGREEN;");
            progressBar.setProgress(1.0);
            System.out.println("Thread end.");
        } else {
            progressBar.setProgress(progress);

        }
    }

}
@Override
    public void run() {
        if (chkBoxSaveEdits.isSelected() && isEdited) {
            try {
                appProps.saveProperties();
                isEdited = false;
            } catch (IOException ex) {
                updateLog("processFiles can't save edits.", SEVERE);
            }

        }
        if (chkBxVerbose.isSelected()) {
            updateLog("FileName" + Common.COMMA + "HighCut" + Common.COMMA
                    + "LowCut" + Common.COMMA + "MaxDN" + Common.COMMA + "MinDN"
                    + Common.COMMA + "NewMax" + Common.COMMA + "newMin"
                    + Common.COMMA + "numHighs" + Common.COMMA + "numLows");
        }

        long start = System.nanoTime();
        // get a sorted list of files in the folder
        File[] listOfFiles = sourceDir.listFiles();
        Arrays.sort(listOfFiles, (f1, f2) -> f1.compareTo(f2));

        // ignores directoriesI
        int numFilesFound = 0;
        int numTIFsFound = 0;
        double progBarMax = (double) listOfFiles.length;
        ThreadProgress progThread = new ThreadProgress(0.0);
        progThread.run();
        try {
            Thread.sleep(1l, 0);
        } catch (InterruptedException ex) {
            Logger.getLogger(FixBsPixController.class.getName()).log(Level.SEVERE, null, ex);
        }
        for (File inFile : listOfFiles) { // Filter files
            if (inFile.isFile()) {  // exclude folders
                ++numFilesFound;
                // Process only the files of interest
                if (inFile.getName().contains(METADATA)) {
                    copyFile(inFile, new File(destinationDir.getAbsolutePath()
                            + Common.PATH_SEP + inFile.getName()));
                } else {
                    if (inFile.getName().contains(ZIPTIF)
                            || inFile.getName().contains(TIF)) {
                        if ((inFile.getName().contains(BWB)
                                && chkBoxBWB.isSelected())
                                || (inFile.getName().contains(B08)
                                && chkBoxB08.isSelected())
                                || (inFile.getName().contains(B10)
                                && chkBoxB10.isSelected())
                                || (inFile.getName().contains(B12)
                                && chkBoxB12.isSelected())) {
                            ++numTIFsFound;
                            File outFile = new File(destinationDir
                                    + Common.PATH_SEP + inFile.getName());
                            // The file is corrected here
                            fixThePix(inFile, outFile);
                        }
                    }
                    progThread
                            = new ThreadProgress(numTIFsFound / progBarMax);
                    progThread.run();
                    try {
                        Thread.sleep(1l, 0);
                    } catch (InterruptedException ex) {
                        Logger.getLogger(FixBsPixController.class.getName()).log(Level.SEVERE, null, ex);
                    }

                }
            }
        } 
        progThread
                = new ThreadProgress(1.0);
        progThread.run();
        try {
            Thread.sleep(1l, 0);
        } catch (InterruptedException ex) {
            Logger.getLogger(FixBsPixController.class.getName()).log(Level.SEVERE, null, ex);
        }
        btnProcess.setText("Process Images");

        if (numTIFsFound == 0) {
            updateLog("No image files found! Wrong folder?", WARNING);
            updateLog("Might want to delete " + destinationDir, INFO);
        } else {
            updateLog("Files processed " + numFilesFound
                    + "  TIFFs found: " + numTIFsFound, INFO);
            long elapsedTime = System.nanoTime() - start;
            updateLog("Elapsed time: " + elapsedTime / 1_000_000 + " ms.", INFO);
            updateLog(" That's "
                    + ((double) elapsedTime / (double) numFilesFound) / 1_000_000
                    + " ms per file.", INFO);
        }

    }

}

1 Ответ

0 голосов
/ 03 мая 2018

Я проследил за комментарием James_D и написал работоспособную ветку, чтобы манипулировать прогрессом ProgressBar.

/** ThreadProgress updates the progress-bar in real time if
  * started with '.start()'
  */
class ThreadProgress implements Runnable {

    ProgressBar progressBar;

    ThreadProgress(double progress, ProgressBar progressBar) {
        this.progress = progress;
        this.progressBar = progressBar;
    }

    @Override
    public void run() {
        progressBar.setProgress(progress);
    }
}

Я также поместил работающий поток в собственный работающий поток и запустил его. в методе handleBtnProcessImagesClick.

@FXML
private void handleBtnProcessImagesClick(ActionEvent event) {
    Thread qif = new Thread(new QueueImageFiles());
    qif.start();
}

Затем в ветке qif (рабочий) я обновил ProgressBar, когда это необходимо.

// first invocation
Thread progThread = new Thread(new ThreadProgress(0.0, progressBar));
progThread.start();

Это работает, и я удовлетворен, но я не могу изменить цвет индикатора выполнения.

...