JavaFX方法内更新进度条

5

我在UI中有一个JavaFX进度条,然后我有一个for循环。 在每次循环迭代中会发生以下事件:

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

整个循环结束后,会发生以下情况:

progress.setProgress(100);

我现在意识到UI控件只有在方法完成后才会刷新,因此进度条直到结束才会更新,然后立即设置为100。

那么是否有可能在方法没有完全完成时强制更新UI?或者我应该如何处理?


1
你已经查看过了吗:http://docs.oracle.com/javafx/2/ui_controls/progress.htm? - crusam
3个回答

12
如果您在循环中执行的操作需要很长时间,并且不应该在JavaFX应用程序线程上执行(如果不是这样,您可能不会有这个问题),那么您应该在不同的线程中使用任务运行循环,并随着循环进展更新任务的进度,将进度条的值绑定到任务的进度。

进度

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);
    }
}
如果任务调用的方法只执行单一任务,不希望它被反复调用怎么办?
那么请移除循环,并在任务进行中通过多次调用来更新进度。该循环仅出现在此示例中是为了演示目的,因为这正是原始问题所要求的。
例如,假设您的任务有三个阶段:从数据库提取数据、执行计算和累积结果,每个阶段分别占总时间的估计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);

2

Java Doc引用如下:

进度指示器的实际进度。负值表示进度不确定。介于0和1之间的正值表示进度的百分比,其中0为0%,1为100%。大于1的任何值都被解释为100%。

简单来说,这意味着您必须将您的值除以100,或者您可以将值增加0.05而不是0.5。

Happy Coding,
Kalasch


0

我的朋友向我展示了使用它的例子。你可以这样做:

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

而刷新进度条则在另一个线程中


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接