繁体   English   中英

JavaFX刷新方法中的进度条

[英]JavaFX refresh Progress Bar within a method

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

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

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

progress.setProgress(100);

我现在已经认识到UI控件只在方法完成后刷新,所以进度条不会更新直到结束,而不是imidatly设置为100。

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

如果你在你的循环中做了很长时间并且不应该在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);

来自Java Doc的报价:

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

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

快乐的编码,
Kalasch

我的朋友告诉我使用它的例子。 你可以这样做:

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

刷新进度条位于其他Thread中

暂无
暂无

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

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