JavaFX创建准确的ProgressBars

时间:2016-05-13 06:54:00

标签: java javafx

我环顾四周,找不到任何体面的片段,告诉你如何创建准确的进度条。通过使用Thread.sleep(10)来指示执行“工作”的线程上的一些工作负载,我见过的所有这些都是廉价的黑客攻击。在某些情况下,这是非常不准确的,因为它实际上没有考虑线程工作负载。我也不想使用不确定的进度条,因为那些看起来很糟糕。

我的问题是:如何创建一个准确的进度条(非不确定),该线程与执行所有“工作”的线程并行运行,在这种情况下将数千个图像写入目录。如果您不知道线程的工作负载,并且您不知道实际转储所有这些线程需要多长时间。解决这个问题的最佳方法是什么?我试图让这个变得现实,而不是仅为化妆品显示进度条。

所以,假设我有一个这样的程序。

      @FXML
  private void dump(ActionEvent e) {
        try {
                 if (e.getSource() == spriteDumpMI) {

                    Thread thread = new Thread(() -> {

                          try (Cache cache = new Cache(FileStore.open(Constants.CACHE_PATH))) {
                                ReferenceTable table = ReferenceTable.decode(Container
                                            .decode(cache.getStore().read(255, 8)).getData());

                                Platform.runLater(() -> {
                                      createTask(10, table.capacity());
                                });


                                for (int i = 0; i < table.capacity(); i++) {
                                      if (table.getEntry(i) == null)
                                            continue;

                                      Container container = cache.read(8, i);
                                      Sprite sprite = Sprite.decode(container.getData());

                                      File dir = new File(Constants.SPRITE_PATH);

                                      if (!dir.exists()) {
                                            dir.mkdir();
                                      }

                                      for (int frame = 0; frame < sprite.size(); frame++) {
                                            File file = new File(Constants.SPRITE_PATH,
                                                        i + "_" + frame + ".png");
                                            BufferedImage image = sprite.getFrame(frame);

                                            ImageIO.write(image, "png", file);
                                      }

                                }
                          } catch (FileNotFoundException e1) {
                                e1.printStackTrace();
                          } catch (IOException e1) {
                                e1.printStackTrace();
                          }

                    });

                    thread.start();

              }
        } catch (Exception ex) {
              ex.printStackTrace();
        }
  }

程序很简单,基本上它会写入存档中的所有精灵(可以是几千张图像)并将所有精灵写入目录,以便用户可以使用它们。

我正在使用此更新我的进度条。

                                    Platform.runLater(() -> {
                                      // this is bad
                                      createTask(10, table.capacity());
                                });

我知道我可以更新循环中的进度条,但是我不知道如何在不创建大量线程和新任务的情况下做到这一点(这也非常糟糕)

方法createTask

      private void createTask(int workload, int max) {

        Task<Boolean> task = taskCreator(workload, max);

        progressBar.setVisible(true);
        progressI.setVisible(true);

        progressBar.progressProperty().unbind();
        progressBar.progressProperty().bind(task.progressProperty());

        progressI.progressProperty().unbind();
        progressI.progressProperty().bind(task.progressProperty());

        new Thread(task).start();
  }

  private Task<Boolean> taskCreator(int workload, int max) {
        return new Task<Boolean>() {

              @Override
              protected Boolean call() throws Exception {

                    progressText.setText("In Progress");
                    progressText.setFill(Color.WHITE);

                    for (int index = 0; index < max; index++) {
                          Thread.sleep(workload);

                          updateProgress(index, max);
                    }

                    progressText.setText("Complete!");
                    progressText.setFill(Color.GREEN);

                    Thread.sleep(1000);

                    progressBar.setVisible(false);
                    progressI.setVisible(false);
                    progressText.setText("");

                    return true;

              }

        };
  }

1 个答案:

答案 0 :(得分:0)

希望这可以提供帮助。

 @FXML
 private void dump(ActionEvent e) {

    try {
             if (e.getSource() == spriteDumpMI) {

                progressBar.setVisible(true);
                progressI.setVisible(true);

                progressBar.progressProperty().unbind();
                progressBar.progressProperty().bind(task.progressProperty());

                progressI.progressProperty().unbind();
                progressI.progressProperty().bind(task.progressProperty());

                progressText.textProperty().unbind();
                progressText.textProperty().bind(task.messageProperty());
                progressText.setFill(Color.GREEN);

                Task task = new Task<Boolean>() {

                  @Override
                  protected Boolean call() throws Exception {
                        updateMessage("In Progress");

                        try (Cache cache = new Cache(FileStore.open(Constants.CACHE_PATH))) {
                                ReferenceTable table = ReferenceTable.decode(Container
                                            .decode(cache.getStore().read(255, 8)).getData());
                                long count;
                                for (int i = 0; i < table.capacity(); i++) {
                                      if (table.getEntry(i) == null)
                                            continue;

                                      Container container = cache.read(8, i);
                                      Sprite sprite = Sprite.decode(container.getData());

                                      File dir = new File(Constants.SPRITE_PATH);

                                      if (!dir.exists()) {
                                            dir.mkdir();
                                      }

                                      for (int frame = 0; frame < sprite.size(); frame++) {
                                            count++;
                                      }

                                }

                                int current;
                                for (int i = 0; i < table.capacity(); i++) {
                                      if (table.getEntry(i) == null)
                                            continue;

                                      Container container = cache.read(8, i);
                                      Sprite sprite = Sprite.decode(container.getData());

                                      File dir = new File(Constants.SPRITE_PATH);

                                      if (!dir.exists()) {
                                            dir.mkdir();
                                      }

                                      for (int frame = 0; frame < sprite.size(); frame++) {
                                            File file = new File(Constants.SPRITE_PATH,
                                                        i + "_" + frame + ".png");
                                            BufferedImage image = sprite.getFrame(frame);

                                            ImageIO.write(image, "png", file);
                                            current++;
                                            updateProgress(current, count);
                                      }

                                }
                                updateMessage("Complete!");
                                Platform.runLater(() -> {
                                    progressText.setFill(Color.GREEN);
                                });
                          } catch (FileNotFoundException e1) {
                                e1.printStackTrace();
                                updateMessage("failed!");
                                Platform.runLater(() -> {
                                    progressText.setFill(Color.GREEN);
                                });
                          } catch (IOException e1) {
                                e1.printStackTrace();
                                updateMessage("failed!");
                                Platform.runLater(() -> {
                                    progressText.setFill(Color.GREEN);
                                });
                          }
                        return true;

                      }

                };

          }
          task.setOnSucceeded(e ->{
                progressBar.setVisible(false);
                progressI.setVisible(false);
                progressText.setText("");
          });
          task.setOnFailed(e ->{
                progressBar.setVisible(false);
                progressI.setVisible(false);
                progressText.setText("");
          });

          new Thread(task).start();
    } catch (Exception ex) {
          ex.printStackTrace();
    }

}