简体   繁体   English

JavaFX刷新方法中的进度条

[英]JavaFX refresh Progress Bar within a method

I have a javafx Progressbar in my UI and then I have a for loop. 我的UI中有一个javafx Progressbar然后我有一个for循环。 In every iteration of the for loop this happens: 在for循环的每次迭代中都会发生这种情况:

progressVal += 5.0;
progress.setProgress(progressVal);

And after the whole loop, this happens: 在整个循环之后,会发生这种情况:

progress.setProgress(100);

I now have recognized that the UI controls are only refreshed after the method has finished, so the progress bar wont update until the end and than would be set to 100 imidiatly. 我现在已经认识到UI控件只在方法完成后刷新,所以进度条不会更新直到结束,而不是imidatly设置为100。

So is it possible so somehow force the UI update, even when the method isn`t finished completly? 那么有可能以某种方式强制UI更新,即使该方法没有完成完成? Or how else could I do this? 或者我怎么能这样做?

If what you do in your loop takes a long time and should not be executed on the JavaFX application thread, (which it probably does or you probably wouldn't have this question), then you should probably run the loop in a Task , on a different thread, updating the task's progress as the loop progresses and binding the progress bar's value to the task's progress. 如果你在你的循环中做了很长时间并且不应该在JavaFX应用程序线程上执行(它可能会执行或者你可能没有这个问题),那么你应该在一个Task中运行循环,一个不同的线程,在循环进行时更新任务的进度,并将进度条的值绑定到任务的进度。

进展

import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class ProgressFeedback extends Application {
    private static final double EPSILON = 0.0000005;
    @Override
    public void start(Stage stage) throws Exception {
        final Task<Void> task = new Task<Void>() {
            final int N_ITERATIONS = 100;

            @Override
            protected Void call() throws Exception {
                for (int i = 0; i < N_ITERATIONS; i++) {
                    updateProgress(i + 1, N_ITERATIONS);
                    // sleep is used to simulate doing some work which takes some time....
                    Thread.sleep(10);
                }

                return null;
            }
        };

        final ProgressBar progress = new ProgressBar();
        progress.progressProperty().bind(
                task.progressProperty()
        );
        // color the bar green when the work is complete.
        progress.progressProperty().addListener(observable -> {
            if (progress.getProgress() >= 1 - EPSILON) {
                progress.setStyle("-fx-accent: forestgreen;");
            }
        });

        // layout the app
        final StackPane layout = new StackPane(progress);
        layout.setPadding(new Insets(10));
        stage.setScene(new Scene(layout));
        stage.show();

        final Thread thread = new Thread(task, "task-thread");
        thread.setDaemon(true);
        thread.start();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

what if the task makes call to a method that does only a single job , and do not want it to be called again and again? 如果任务调用只执行单个作业的方法,并且不希望一次又一次地调用它,该怎么办?

Then remove the loop and invoke updateProgress through multiple calls within the job as the job progresses. 然后删除循环并在作业进行时通过作业内的多个调用调用updateProgress。 The loop is only present in this sample for demonstration purposes and because this is what the original question specifically asked about. 该循环仅出于演示目的而出现在此示例中,因为这是原始问题的具体问题。

For example lets say your job has 3 stages: fetch from database, perform calculation and accumulate results. 例如,假设您的工作有3个阶段:从数据库中获取,执行计算并累积结果。 Each stage taking an estimated 30 percent, 60 percent and 10 percent of total time respectively, then you can do something like this within the call() body of your task: 每个阶段分别占总时间的30%,60%和10%,然后你可以在任务的call()体内执行类似的操作:

updateProgress(0, 1.0);
Data data = db.fetchData(query);
updateProgress(0.3, 1.0);
ProcessedData processed = calculator.process(data);
updateProgress(0.9, 1.0);
Result result = accumulator.reduce(processed);
updateProgress(1.0, 1.0);

Quotation from Java Doc : 来自Java Doc的报价:

The actual progress of the ProgressIndicator. ProgressIndicator的实际进度。 A negative value for progress indicates that the progress is indeterminate. 进度的负值表示进度是不确定的。 A positive value between 0 and 1 indicates the percentage of progress where 0 is 0% and 1 is 100%. 0到1之间的正值表示进度百分比,其中0表示0%,1表示100%。 Any value greater than 1 is interpreted as 100%. 任何大于1的值都被解释为100%。

That means in simple words, you must divide you value with 100, or you just increment the value by 0.05 instead of 0.5. 这意味着简单来说,你必须将值除以100,或者只是将值增加0.05而不是0.5。

Happy Coding, 快乐的编码,
Kalasch Kalasch

My friend show me example of using that. 我的朋友告诉我使用它的例子。 You could do this: 你可以这样做:

Platform.runLater(new Runnable() {
            @Override public void run() {
                bar.setProgress(counter/1000000.0);
            }
        });

And the refresh progress bar is in other Thread 刷新进度条位于其他Thread中

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM