6

我试图了解如何在多线程环境中更新 ProgressBar。我在这里做错了什么,但我不明白它是什么。这应该只是每 3 秒填满一次,但它不会:

    Task<Void> task = new Task<Void>(){
        @Override
        public Void call(){
            for (int i = 1; i < 10; i++)    {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(i);
                updateProgress(i , 10);
            }
        return null;                
        }
    };

    updProg = new ProgressBar();
    updProg.progressProperty().bind(task.progressProperty());

    Thread th = new Thread(task);
    th.setDaemon(true);
    th.start();

我错过了什么?

4

4 回答 4

9

你的样品对我来说很好。

样品每 3 秒填充一点点,半分钟内完全填满。

我只是将它包装在一些脚手架代码中以使其可执行并且无需更改即可工作(java7u15,win7)。

简单任务进度

import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class ProgressTest extends Application {
  public static void main(String[] args) { Application.launch(args); }
  @Override public void start(Stage stage) {
    Task<Void> task = new Task<Void>() {
      @Override public Void call() {
        for (int i = 0; i < 10; i++) {
          try {
            Thread.sleep(100);
          } catch (InterruptedException e) {
            Thread.interrupted();
            break;
          }
          System.out.println(i + 1);
          updateProgress(i + 1, 10);
        }
        return null;
      }
    };

    ProgressBar updProg = new ProgressBar();
    updProg.progressProperty().bind(task.progressProperty());

    Thread th = new Thread(task);
    th.setDaemon(true);
    th.start();

    StackPane layout = new StackPane();
    layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 10;");
    layout.getChildren().add(updProg);

    stage.setScene(new Scene(layout));
    stage.show();
  }
}

也许您一直在使用 Java 8 的一些早期访问版本,其中包含有关 ProgressBar 更新的错误(现已修复)。

RT-29018 ProgressBar 和 ProgressIndicator 在更新 progressProperty 时消失

于 2013-03-19T23:46:41.650 回答
1

您使用的是最新的 JDK 8 Early-Access 吗?如果是这样,请参阅我提交的此错误报告:http: //javafx-jira.kenai.com/browse/RT-29018

基本上,在最近发布的抢先体验版本中,他们对皮肤和 css 进行了一些更改。这导致了一个隐藏的错误被揭示,其中子节点比父节点更脏但都需要在相同的脉冲中重新绘制,父节点的脏级别最终会覆盖子节点的脏级别。

这导致进度不显示,事实上,对我来说progressBar,一旦updateProgress从任务中调用,它就变得完全不可见。他们有一个补丁,我不知道什么时候会通过。

一种解决方法,要么在等待补丁时使用 jdk7,要么你可以做我所做的并将旧 css 中的它应用到你的 css 样式表中:

/*hack to get progress bar working. From: JDK7u17 jfxrt.jar!/com/sun/javafx/scene/control/skin/caspian/caspian.css */

/*******************************************************************************
 *                                                                             *
 * ProgressBar                                                                 *
 *                                                                             *
 ******************************************************************************/

.progress-bar {
    -fx-skin: "com.sun.javafx.scene.control.skin.ProgressBarSkin";
    -fx-background-color:
        -fx-box-border,
        linear-gradient(to bottom, derive(-fx-color,30%) 5%, derive(-fx-color,-17%));
    -fx-background-insets: 0, 1;
    -fx-indeterminate-bar-length: 60;
    -fx-indeterminate-bar-escape: true;
    -fx-indeterminate-bar-flip: true;
    -fx-indeterminate-bar-animation-time: 2;
    -fx-focus-traversable: true;
}

.progress-bar .bar {
    -fx-background-color:
        -fx-box-border,
        linear-gradient(to bottom, derive(-fx-accent,95%), derive(-fx-accent,10%)),
        linear-gradient(to bottom, derive(-fx-accent,38%), -fx-accent);
    -fx-background-insets: 0, 1, 2;
    -fx-padding: 0.416667em; /* 5 */
}

.progress-bar:indeterminate .bar {
    -fx-background-color: linear-gradient(to left, transparent, -fx-accent);
}

.progress-bar .track {
     -fx-background-color:
        -fx-box-border,
        linear-gradient(to bottom, derive(-fx-color,-15%), derive(-fx-color,2.2%) 20%, derive(-fx-color,60%));
    -fx-background-insets:  0, 1;
}

.progress-bar:disabled {
    -fx-opacity: 1.0
}
于 2013-03-21T08:41:26.870 回答
0

如果您在 FXML 文件中定义了 updProg,那么问题可能是这里的初始化。

尝试删除这一行:

updProg = new ProgressBar();
于 2015-11-18T15:24:49.313 回答
0
 Timeline updateProgressBar = new Timeline(new KeyFrame(Duration.seconds(1), new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                      /*Where Seconds and TotalSeconds are counter and total
                      respectively, also put somewhere Seconds++ or 
                      however you want to update progress. This time line 
                      will reapit each second */
                      progressBar.setProgress(Seconds / TotalSeconds);
                }
    }));
    updateProgressBar.setCycleCount(Timeline.INDEFINITE);
    updateProgressBar.play();
于 2017-11-21T11:22:23.587 回答