title: Display Circle progress bar during charts loading
body: <p>I'm working on this code with Barchart and Piechart.</p>
  
  <pre><code>import java.sql.Timestamp;
  import java.util.LinkedList;
  import java.util.List;
  import java.util.Random;
  import javafx.application.Application;
  import static javafx.application.Application.launch;
  import javafx.application.Platform;
  import javafx.beans.binding.Bindings;
  import javafx.beans.value.ChangeListener;
  import javafx.beans.value.ObservableObjectValue;
  import javafx.beans.value.ObservableValue;
  import javafx.collections.FXCollections;
  import javafx.collections.ObservableList;
  import javafx.concurrent.Task;
  import javafx.geometry.Bounds;
  import javafx.geometry.Insets;
  import javafx.geometry.Pos;
  import javafx.scene.Group;
  import javafx.scene.Node;
  import javafx.scene.Parent;
  import javafx.scene.Scene;
  import javafx.scene.chart.BarChart;
  import javafx.scene.chart.CategoryAxis;
  import javafx.scene.chart.NumberAxis;
  import javafx.scene.chart.PieChart;
  import javafx.scene.chart.XYChart;
  import javafx.scene.control.ComboBox;
  import javafx.scene.control.Label;
  import javafx.scene.control.ProgressIndicator;
  import javafx.scene.layout.BorderPane;
  import javafx.scene.layout.HBox;
  import javafx.scene.layout.Pane;
  import javafx.scene.layout.StackPane;
  import javafx.scene.layout.VBox;
  import javafx.scene.text.Text;
  import javafx.stage.Stage;
  
  public class MainApp extends Application
  {
  
      @Override
      public void start(Stage stage) throws Exception
      {
          Scene scene = new Scene(initGeneralAgentsData(), 800, 800);
          stage.setScene(scene);
          stage.show();
      }
  
      public static void main(String[] args)
      {
          launch(args);
      }
  
      private final StackPane stackPane = new StackPane();
      private List&lt;DownloadTrafficObj&gt; obj = new LinkedList&lt;&gt;();
  
      public StackPane initGeneralAgentsData() throws Exception
      {
          stackPane.setAlignment(Pos.TOP_RIGHT);
          stackPane.setStyle("-fx-background-color: white;");
  
          SQLSelect(30);
          stackPane.getChildren().addAll(chartChoose());
          return stackPane;
      }
  
      private List&lt;DownloadTrafficObj&gt; SQLSelect(int history_value)
      {
          for (int i = 0; i &lt; history_value; i++)
          {
              obj.add(new DownloadTrafficObj(String.valueOf(randomDate()), Long.valueOf(randomNumber())));
          }
  
          return obj;
      }
  
  
  
  
  
  
      private Timestamp randomDate()
      {
          long offset = Timestamp.valueOf("2012-01-01 00:00:00").getTime();
          long end = Timestamp.valueOf("2013-01-01 00:00:00").getTime();
          long diff = end - offset + 1;
          Timestamp rand = new Timestamp(offset + (long) (Math.random() * diff));
  
          return rand;
      }
  
      private int randomNumber()
      {
          Random rand = new Random();
          int n = rand.nextInt(50) + 1;
          return n;
      }
  
      public StackPane chartChoose()
      {
          final ComboBox comboBox = new ComboBox();
          comboBox.getItems().addAll("Bar Chart", "Pie Chart");
  
          ComboBox cb = new ComboBox();
          cb.getItems().addAll(10, 20, 30, 60);
          cb.setValue(30);
  
          final StackPane stack = new StackPane();
  
          comboBox.getSelectionModel().selectedIndexProperty()
              .addListener((ObservableValue&lt;? extends Number&gt; observable,
                      Number oldValue, Number newValue)
                  -&gt; setVisibility(stack, comboBox)
              );
  
          cb.getSelectionModel().selectedIndexProperty()
              .addListener((ObservableValue&lt;? extends Number&gt; observable,
                      Number oldValue, Number newValue)
                  -&gt;
                  {
                      SQLSelect((int) cb.getSelectionModel().getSelectedItem());
                      bc.getData().clear();
                      generateBarChartData();
              }
              );
  
          stack.getChildren().add(generateBarChart());
          stack.getChildren().add(generatePieChart());
  
          // Placing it after adding rectangle to stack
          // will trigger the changelistener to show default rectangle
          comboBox.setValue("Bar Chart");
  
          VBox vBox = new VBox();
          vBox.setPadding(new Insets(10, 10, 10, 10));
          vBox.setSpacing(5);
  
          Label labelon = new Label("Chart type");
          Label label = new Label("Days history");
          HBox hBossx = new HBox(15, labelon, comboBox, label, cb);
          hBossx.setAlignment(Pos.CENTER_RIGHT);
  
  
  
          ProgressIndicator progress = new ProgressIndicator();
          progress.setMaxSize(90, 90);
          Task&lt;ObservableList&lt;DownloadTrafficObj&gt;&gt; task = new Task&lt;ObservableList&lt;DownloadTrafficObj&gt;&gt;()
          {
              @Override
              protected ObservableList&lt;DownloadTrafficObj&gt; call() throws Exception
              {
                  for (int i = 0; i &lt; 99; i++)
                  {
                      Thread.sleep(20);
                   }
                   return (FXCollections.observableArrayList(obj));
              }
          };
  
          progress.progressProperty().bind(task.progressProperty());
          task.setOnSucceeded(ev -&gt;
          {
  
          });
          new Thread(task).start();
  
  
          BorderPane bp = new BorderPane();
  
          bp.centerProperty().bind(
              Bindings
              .when(task.runningProperty())
              .then(progress)
              .otherwise((ObservableObjectValue&lt;ProgressIndicator&gt;) stack));
  
  
          vBox.getChildren().addAll(hBossx, bp);
  
          StackPane root = new StackPane();
          root.getChildren().add(vBox);
  
          return root;
      }
  
      public void setVisibility(Pane pane, ComboBox comboBox)
      {
          // Make all children invisible
          pane.getChildren().stream().forEach((node) -&gt;
          {
              node.setVisible(false);
          });
          // make the selected rectangle visible
          int selectedIndex = comboBox.getSelectionModel()
              .selectedIndexProperty().getValue();
          pane.getChildren().get(selectedIndex).setVisible(true);
      }
  
      final CategoryAxis xAxis = new CategoryAxis();
      final NumberAxis yAxis = new NumberAxis();
      final BarChart&lt;String, Number&gt; bc = new BarChart&lt;&gt;(xAxis, yAxis);
      XYChart.Series series1 = new XYChart.Series();
  
      public BarChart&lt;String, Number&gt; generateBarChart()
      {
          bc.setTitle("Network Download");
          xAxis.setLabel("Groups");
          yAxis.setLabel("Value");
  
          series1.setName("Network Download");
  
          generateBarChartData();
  
          // TO DO... Very quick fix.
          bc.widthProperty().addListener((obs, b, b1) -&gt;
          {
              // Chart Bar column is not automatically resized. We need to wait for next JavaFX releases to fix this.
              Platform.runLater(() -&gt; setMaxBarWidth(bc, xAxis, 40, 10));
          });
  
          bc.getData().addAll(series1);
          return bc;
      }
  
      private void generateBarChartData()
      {
          obj.stream().map((get) -&gt; new XYChart.Data(get.getDate(), get.getDownloadTraffic())).map((data) -&gt;
          {
              data.nodeProperty().addListener(new ChangeListener&lt;Node&gt;()
              {
                  @Override
                  public void changed(ObservableValue&lt;? extends Node&gt; ov, Node oldNode, final Node node)
                  {
                      if (node != null)
                      {
                          //setNodeStyle(data);
                          displayLabelForData(data);
                      }
                  }
              });
              return data;
          }).forEach((data) -&gt;
          {
              series1.getData().add(data);
          });
      }
  
      private void setMaxBarWidth(BarChart&lt;String, Number&gt; bc, CategoryAxis xAxis, double maxBarWidth, double minCategoryGap)
      {
          double barWidth = 0;
          do
          {
              double catSpace = xAxis.getCategorySpacing();
              double avilableBarSpace = catSpace - (bc.getCategoryGap() + bc.getBarGap());
              barWidth = (avilableBarSpace / bc.getData().size()) - bc.getBarGap();
              if (barWidth &gt; maxBarWidth)
              {
                  avilableBarSpace = (maxBarWidth + bc.getBarGap()) * bc.getData().size();
                  bc.setCategoryGap(catSpace - avilableBarSpace - bc.getBarGap());
              }
          }
          while (barWidth &gt; maxBarWidth);
  
          do
          {
              double catSpace = xAxis.getCategorySpacing();
              double avilableBarSpace = catSpace - (minCategoryGap + bc.getBarGap());
              barWidth = Math.min(maxBarWidth, (avilableBarSpace / bc.getData().size()) - bc.getBarGap());
              avilableBarSpace = (barWidth + bc.getBarGap()) * bc.getData().size();
              bc.setCategoryGap(catSpace - avilableBarSpace - bc.getBarGap());
          }
          while (barWidth &lt; maxBarWidth &amp;&amp; bc.getCategoryGap() &gt; minCategoryGap);
      }
  
      public PieChart generatePieChart()
      {
          ObservableList&lt;PieChart.Data&gt; pieChartData = FXCollections.observableArrayList();
  
          obj.stream().forEach((activeAgentGroup) -&gt;
          {
              pieChartData.add(new PieChart.Data(activeAgentGroup.getDate(), activeAgentGroup.getDownloadTraffic()));
          });
  
          final PieChart chart = new PieChart(pieChartData);
  
          chart.setTitle("Label");
  
          return chart;
      }
  
      private void displayLabelForData(XYChart.Data&lt;String, Number&gt; data)
      {
          final Node node = data.getNode();
          final Text dataText = new Text(data.getYValue().toString());
          node.parentProperty().addListener(new ChangeListener&lt;Parent&gt;()
          {
              @Override
              public void changed(ObservableValue&lt;? extends Parent&gt; ov, Parent oldParent, Parent parent)
              {
                  Group parentGroup = (Group) parent;
                  parentGroup.getChildren().add(dataText);
              }
          });
  
          node.boundsInParentProperty().addListener(new ChangeListener&lt;Bounds&gt;()
          {
              @Override
              public void changed(ObservableValue&lt;? extends Bounds&gt; ov, Bounds oldBounds, Bounds bounds)
              {
                  dataText.setLayoutX(
                      Math.round(
                          bounds.getMinX() + bounds.getWidth() / 2 - dataText.prefWidth(-1) / 2
                      )
                  );
                  dataText.setLayoutY(
                      Math.round(
                          bounds.getMinY() - dataText.prefHeight(-1) * 0.5
                      )
                  );
              }
          });
      }
  }
  </code></pre>
  
  <p>I ant to add circular progress bar during switch of the charts and loading of the data. Usually it takes 2-3 seconds to load data from the database, so I need a way to display progress bay because the charts are stacked.
  Also is there any much easy way to implement the switching of the charts? </p>