【问题标题】:JavaFX refresh Progress Bar within a methodJavaFX在方法内刷新进度条
【发布时间】:2014-06-20 11:33:11
【问题描述】:

我的 UI 中有一个 javafx 进度条,然后我有一个 for 循环。 在 for 循环的每次迭代中都会发生这种情况:

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

在整个循环之后,会发生这种情况:

progress.setProgress(100);

我现在已经认识到 UI 控件仅在方法完成后才会刷新,因此进度条直到结束才会更新,并且会立即设置为 100。

那么是否有可能以某种方式强制 UI 更新,即使该方法没有完全完成?或者我还能怎么做?

【问题讨论】:

标签: java javafx progress-bar


【解决方案1】:

如果您在循环中执行的操作需要很长时间并且不应该在 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);
    }
}

如果任务调用一个只做一个工作的方法,并且不希望它被一次又一次地调用怎么办?

然后移除循环并在作业进行时通过作业内的多次调用调用 updateProgress。该循环仅出于演示目的而出现在此示例中,因为这是原始问题专门询问的内容。

例如,假设您的工作有 3 个阶段:从数据库中获取、执行计算和累积结果。每个阶段估计分别占用总时间的 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:

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

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

    快乐编码,
    卡拉施

    【讨论】:

      【解决方案3】:

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

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

      并且刷新进度条在其他线程中

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多