Java FXML ProgressBar不会更新,直到所有工作完成

时间:2018-05-01 15:47:00

标签: multithreading javafx progress-bar desktop-application scenebuilder

我试图通过移植命令行Java应用程序来使用Scene Builder和NetBeans来学习Java FX,并且大部分都在使用它。然而,在工人完成之前,进度条和文本区域都不会更新。"处理图像"按钮不表示已被点击,5秒或更长时间后光标显示应用程序正忙。我使用NetBeans-> New Project-> JavaFX-> Java FXML应用程序启动了该项目。我的代码在Controller文件中。

我已经了解(感谢Google),这是此类GUI的正常行为,并且更新需要在他们自己的线程中,而不是如何创建我需要的线程。

我创建了一个嵌套线程只是为了增加进度条,它没有用。然后我为使用进度线程的worker创建了一个嵌套线程,没有任何改变。然后我嵌套了嵌套worker中的进度线程,但仍然没有变化。工作方法/线程管理过滤它们的文件列表,并一次一个地提交正确的文件到一个方法,该方法可以纠正可能发现的任何错误。工作线程负责更新进度条,文本区域的更新是修复'修复的方法的责任。文件。

此按钮单击开始处理。

    @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 :(得分:0)

我跟进了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);
    }
}

我还将工作放入自己的runnable线程并启动它 在' handleBtnProcessImagesClick'方法

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

然后,在qif(worker)线程中,我在需要时更新了ProgressBar。

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

这很有效,我很满意,但我不能做的是改变进度条的颜色。