5 Replies Latest reply: Feb 10, 2013 7:09 PM by James_D RSS

    AreaChart, change the axis range

    990250
      Hello, I'm new to Java FX, and I'm having some issues with Charts.

      I will detail what I have done to see if it makes sense to work this way or not.

      1) I create a javaFX aplication
      2) I create a GUI with JavaFx Scene Builder.
      3) this GUI contains an AreaChartNxN
      4) I have a routine computing a data vector of 8760 values, (I want to plot the data in ranges of 24, i.e. data[0..24] or data[24..48] etc...)


      Problem:
      When I load a Serie<X,Y> where X goes from i.e. 1024 to 1048, the X axis of the AreaChart still has its origin in Zero, making the plot unusable (the Data sees too small)

      So I google for the answer, an I find that, once created, a Chart cannot modify its Axis bounds (WTF??!! seriously?)

      All the documentation explains is to create a new AreaChart in a new scene, by doing this, the boundaries are ok but the data serie does not appear.

      What I Want:
      I Want my plot in my UI with the boundaries in range.
      I think, what I should do is to create a new AreaChart object every time, and somehow load it into my javaFX GUI, but I don't know how to do this. in Swing I used to load Plots in JPanels but in javaFX I don't know how to do it.

      This is what I have for now:


      +public void addSerie(AreaChart ac, XYChart.Series serie, String title, String xlabel, String ylabel, int xmin, int xmax) {+

      ac.getXAxis().setAutoRanging(true);
      ac.setTitle(title);
      ac.getData().add(serie);
      ac.getXAxis().setLabel(xlabel);
      ac.getYAxis().setLabel(ylabel);

      +}+

      Any advice would be appreciated.
        • 1. Re: AreaChart, change the axis range
          James_D
          The NumberAxis (I assume you're using a number axis) has a bunch of methods that should help:
          yAxis.setForceZeroInRange(false);
          should do the trick, but if you need more control you can do
          yAxis.setAutoRange(false);
          yAxis.setLowerBound(...);
          yAxis.setUpperBound(...);
          I don't think you'd need to create a new chart every time, but even if you do it's not hard. The exact code depends on the Parent that contains the chart. Probably the easiest is if your chart sits in a BorderPane. Then all you'd need is something like
          borderPane.setCenter(newChart);
          • 2. Re: AreaChart, change the axis range
            bouye
            I have no issue changing the bounds by using setLowerBound() and setUpperBound() on the X axis event is 0 is not within bounds.
            • 3. Re: AreaChart, change the axis range
              James_D
              Sorry; I missed that the issue was on the x axis. Doesn't the code I posted work equally well for the x axis as the y axis?
              • 4. Re: AreaChart, change the axis range
                James_D
                import java.util.Random;
                
                import javafx.application.Application;
                import javafx.event.ActionEvent;
                import javafx.event.EventHandler;
                import javafx.scene.Scene;
                import javafx.scene.chart.AreaChart;
                import javafx.scene.chart.NumberAxis;
                import javafx.scene.chart.XYChart.Data;
                import javafx.scene.chart.XYChart.Series;
                import javafx.scene.control.Button;
                import javafx.scene.layout.BorderPane;
                import javafx.stage.Stage;
                
                public class AreaChartTest extends Application {
                
                  private int sequence = 0;
                
                  @Override
                  public void start(Stage primaryStage) {
                    final BorderPane root = new BorderPane();
                    final NumberAxis xAxis = new NumberAxis();
                    final NumberAxis yAxis = new NumberAxis();
                    final AreaChart<Number, Number> chart = new AreaChart<>(xAxis, yAxis);
                    final Button button = new Button("Next series");
                
                    xAxis.setForceZeroInRange(false);
                    chart.setAnimated(false);
                
                    button.setOnAction(new EventHandler<ActionEvent>() {
                      @Override
                      public void handle(ActionEvent event) {
                        chart.getData().clear();
                        chart.getData().add(createSeries());
                      }
                    });
                
                    root.setCenter(chart);
                    root.setBottom(button);
                
                    Scene scene = new Scene(root, 600, 600);
                    primaryStage.setScene(scene);
                    primaryStage.show();
                  }
                
                  private Series<Number, Number> createSeries() {
                    final Random rng = new Random();
                    Series<Number, Number> series = new Series<>();
                    sequence++;
                    series.setName("Data " + sequence);
                    for (int x = sequence * 24; x < (sequence + 1) * 24; x += 3) {
                      series.getData().add(new Data<Number, Number>(x, rng.nextInt(80) + 10));
                    }
                    return series;
                  }
                
                  public static void main(String[] args) {
                    launch(args);
                  }
                }
                • 5. Re: AreaChart, change the axis range
                  James_D
                  Another solution, perhaps closer to the exact problem you're seeking to solve:
                  import java.util.ArrayList;
                  import java.util.List;
                  import java.util.Random;
                  
                  import javafx.application.Application;
                  import javafx.beans.property.IntegerProperty;
                  import javafx.beans.property.SimpleIntegerProperty;
                  import javafx.beans.value.ChangeListener;
                  import javafx.beans.value.ObservableValue;
                  import javafx.collections.FXCollections;
                  import javafx.collections.ObservableList;
                  import javafx.event.ActionEvent;
                  import javafx.event.EventHandler;
                  import javafx.geometry.Orientation;
                  import javafx.scene.Scene;
                  import javafx.scene.chart.AreaChart;
                  import javafx.scene.chart.NumberAxis;
                  import javafx.scene.chart.XYChart.Data;
                  import javafx.scene.chart.XYChart.Series;
                  import javafx.scene.control.Button;
                  import javafx.scene.control.ScrollBar;
                  import javafx.scene.layout.BorderPane;
                  import javafx.scene.layout.HBox;
                  import javafx.stage.Stage;
                  
                  public class AreaChartTest extends Application {
                  
                    @Override
                    public void start(Stage primaryStage) {
                      final BorderPane root = new BorderPane();
                      final NumberAxis xAxis = new NumberAxis();
                      final NumberAxis yAxis = new NumberAxis();
                      final AreaChart<Number, Number> chart = new AreaChart<>(xAxis, yAxis);
                  
                      xAxis.setForceZeroInRange(false);
                      chart.setAnimated(false);
                  
                      final Series<Number, Number> series = new Series<>();
                      chart.getData().add(series);
                  
                      // build data:
                      final List<Data<Number, Number>> allData = new ArrayList<Data<Number, Number>>();
                      final Random rng = new Random();
                      for (int x = 0; x < 8760; x++) {
                        allData.add(new Data<Number, Number>(x, rng.nextInt(80)));
                      }
                  
                      // Property for the index of the individual screens (each one is 24 data
                      // points wide)
                      final IntegerProperty chartPortionIndex = new SimpleIntegerProperty(-1);
                      // Update data when this index changes
                      chartPortionIndex.addListener(new ChangeListener<Number>() {
                        @Override
                        public void changed(ObservableValue<? extends Number> observable,
                            Number oldValue, Number newValue) {
                          series.setData(FXCollections.observableArrayList(allData.subList(
                              newValue.intValue() * 24, newValue.intValue() * 24 + 23)));
                          series.setName("Data section " + newValue);
                        }
                      });
                  
                      chartPortionIndex.set(0);
                  
                      // Scroller for scrolling through the data set
                      ScrollBar scrollBar = new ScrollBar();
                      scrollBar.setOrientation(Orientation.HORIZONTAL);
                      scrollBar.setMin(0);
                      scrollBar.setMax(8760 / 24 - 1);
                      scrollBar.setUnitIncrement(1);
                  
                      // bind the index to the scroller value:
                      chartPortionIndex.bind(scrollBar.valueProperty());
                  
                      root.setCenter(chart);
                      root.setBottom(scrollBar);
                  
                      Scene scene = new Scene(root, 600, 600);
                      primaryStage.setScene(scene);
                      primaryStage.show();
                    }
                  
                    public static void main(String[] args) {
                      launch(args);
                    }
                  }
                  Edited by: James_D on Feb 10, 2013 5:09 PM (Changed UI to use scroll bar)