更新for循环中的progressbar值

lzfw57am  于 2021-09-13  发布在  Java
关注(0)|答案(2)|浏览(351)

我试图更新一个 ProgressBar for循环中的值。它的进度应该每100毫秒更新一次,但不幸的是它没有工作!代码如下:

pb = new ProgressBar(0);
Button btn = new Button("Start!");
btn.setOnAction(new EventHandler<ActionEvent>(){
    @Override
    public void handle(ActionEvent event) {
        for(int i = 0; i <=100; i++){
            position = i;
            Platform.runLater(new Runnable(){
                @Override
                public void run() {
                    pb.setProgress(position);
                    System.out.println("Index: "+position);
                }
            });
            try{
                Thread.sleep(100);
            }catch(Exception e){ System.err.println(e); }
        }
    }
});

问题1:我希望上面的代码每100毫秒更新一次progressbar,但它没有起作用。为什么?
问题2:我打过电话 System.out.println("Index: "+position); 在循环中。我假设输出应该是 1..2..3..4... 但我错了。输出如下所示:

Index: 100
Index: 100
Index: 100
Index: 100
Index: 100
Index: 100
Index: 100
0sgqnhkj

0sgqnhkj1#

背景 Platform.runLater() 被调用以在 JavaFX Application thread 当你在另一条线上时。当您已经在javafx应用程序线程上添加队列中的所有这些项目时,每100毫秒运行一次,因为该线程已经在忙于运行循环和睡眠:)
因此,它在线程可以自由执行队列中的所有内容后(即完成循环后)运行队列中的所有内容。
还有一个问题,progressbar有一个progressproperty,其值可以介于0和1之间,其中0表示0%,1表示100%。如果要更新进度条,则需要使用0.1到1.0之间的值设置进度。
如何修复
您应该在按钮的操作上启动一个新线程,并让它处理循环。你可以用 Platform.runLater 在这个线程中,不阻塞javafx应用程序线程。
我将运行以下内容:

btn.setOnAction(event -> {
    new Thread(() -> {
         for(int i = 0; i <=100; i++){
            final int position = i;
            Platform.runLater(() -> {
                pb.setProgress(position/100.0);
                System.out.println("Index: " + position);
            });
            try{
                Thread.sleep(100);
            }catch(Exception e){ System.err.println(e); }
         }
    }).start();
});

注意:这个答案更强调op哪里出了问题,以及他如何纠正错误。如果您使用的是javafx,您会希望使用更好的方法,即使用 Task 及其 updateProgress() 更新@kleopatra在其解决方案中所述progressbar的进度。

5lwkijsr

5lwkijsr2#

通过手动计算和设置工具栏的progressproperty来重新发明控制盘的另一种方法是使用任务:它有一个progressproperty,可以自动计算相对数量并保证在fx应用程序线程上更新,这样就可以安全地将任何与场景相关的属性绑定到。
比如:

Task<Void> task = new Task<Void>() {

    @Override
    protected Void call() throws Exception {
        double max = 137;
        for (int i = 0; i <= max; i++) {
            updateProgress(i, max);
            Thread.sleep(100);
        }
        return null;
    }

};
button.setOnAction(e -> {
    // a task is not reusable, disable
    button.setDisable(true);
    // bind "late" to not get an initial indeterminate PB
    bar.progressProperty().bind(task.progressProperty());
    new Thread(task).start();
});

显然,这是最简单的代码片段——请参阅task,以了解取消/中断线程的示例。

相关问题