Kadana Kanz
Kadana Kanz

Reputation: 197

Aligning CategoryAxis and NumberAxis

I'm currently stacking two different charts (BarChart and LineChart) using JavaFX. The LineChart has been divided into three areas to display where the points from the BarChart will fall into.

I am having a problem with my current code where the CategoryAxis from the BarChart and the NumberAxis from the LineChart is not aligning well on the xAxis. This is what it currently looks like:

enter image description here

As you can see (click on the image to zoom in), some of the values along the xAxis does not align. I am unable to use the same NumberAxis for the LineChart and BarChart because BarChart only supports CategoryAxis. Is there any way to fix this so that the values along the xAxis aligns?

Code:

    NumberAxis xAxis = new NumberAxis(0, 6, 1);
    xAxis.setLabel("X");

    NumberAxis yAxis = new NumberAxis(-5, 5, 0.5);
    yAxis.setLabel("Y");

    XYChart.Series<Number, Number> dataSeries1 = new XYChart.Series<>();
    XYChart.Series<Number, Number> dataSeries2 = new XYChart.Series<>();

    dataSeries1.setName("2SD");
    dataSeries2.setName("3SD");

    dataSeries1.getData().add(new XYChart.Data<>(0, 0.6));
    dataSeries1.getData().add(new XYChart.Data<>(1, 0.9));
    dataSeries1.getData().add(new XYChart.Data<>(2, 1.7));
    dataSeries1.getData().add(new XYChart.Data<>(3, 1.8));
    dataSeries1.getData().add(new XYChart.Data<>(4, 1.8));
    dataSeries1.getData().add(new XYChart.Data<>(5, 2.1));
    dataSeries1.getData().add(new XYChart.Data<>(6, 2.3));

    dataSeries2.getData().add(new XYChart.Data<>(0, 1.0));
    dataSeries2.getData().add(new XYChart.Data<>(1, 1.3));
    dataSeries2.getData().add(new XYChart.Data<>(2, 2.4));
    dataSeries2.getData().add(new XYChart.Data<>(3, 2.5));
    dataSeries2.getData().add(new XYChart.Data<>(4, 2.7));
    dataSeries2.getData().add(new XYChart.Data<>(5, 3.1));
    dataSeries2.getData().add(new XYChart.Data<>(6, 3.3));

    final LineChart<Number, Number> lineChart =
            new LineChart<Number, Number>(xAxis, yAxis, FXCollections.observableArrayList(dataSeries2, dataSeries1)) {
                @Override
                protected void layoutPlotChildren() {
                    super.layoutPlotChildren();

                    XYChart.Series a =  getData().get(0);
                    XYChart.Series b =  getData().get(1);
                    ObservableList<XYChart.Data<Number, Number>> aData = a.getData();
                    ObservableList<XYChart.Data<Number, Number>> bData = b.getData();

                    for(int i = 0; i < aData.size()-1; i++){

                        // Color in the area between 2SD and 3SD
                        double x = getXAxis().getDisplayPosition(aData.get(i).getXValue());
                        double y = getYAxis().getDisplayPosition(bData.get(i).getYValue());
                        double x2 = getXAxis().getDisplayPosition(aData.get((i+1)).getXValue());
                        double y2 = getYAxis().getDisplayPosition(bData.get((i+1)).getYValue());

                        Polygon middlePolygon = new Polygon();

                        middlePolygon.getPoints().addAll(x,y,
                                x, getYAxis().getDisplayPosition(aData.get(i).getYValue()),
                                x2,getYAxis().getDisplayPosition(aData.get((i+1)).getYValue()),
                                x2,y2);
                        getPlotChildren().add(middlePolygon);
                        middlePolygon.toFront();
                        middlePolygon.setFill(Color.ORANGE);

                        // Color in the area above 3SD
                        double y3 = getXAxis().getDisplayPosition(0);
                        double y4 = getXAxis().getDisplayPosition(0);

                        Polygon topPolygon = new Polygon();

                        topPolygon.getPoints().addAll(x,y3,
                                x, getYAxis().getDisplayPosition(aData.get(i).getYValue()),
                                x2,getYAxis().getDisplayPosition(aData.get(i+1).getYValue()),
                                x2,y4);
                        getPlotChildren().add(topPolygon);
                        topPolygon.toFront();
                        topPolygon.setFill(Color.RED);

                        // Color in the area below 2SD

                        double xb = getXAxis().getDisplayPosition(bData.get(i).getXValue());
                        double yb = getYAxis().getDisplayPosition(-10);
                        double xb2 = getXAxis().getDisplayPosition(bData.get(i+1).getXValue());
                        double yb2 = getYAxis().getDisplayPosition(-10);

                        Polygon bottomPolygon = new Polygon();

                        bottomPolygon.getPoints().addAll(xb,yb,
                                xb, getYAxis().getDisplayPosition(bData.get(i).getYValue()),
                                xb2,getYAxis().getDisplayPosition(bData.get((i+1)).getYValue()),
                                xb2,yb2
                        );
                        getPlotChildren().add(bottomPolygon);
                        bottomPolygon.toFront();
                        bottomPolygon.setFill(Color.GREEN);

                    }


                }
            };

    lineChart.setCreateSymbols(false);


    CategoryAxis xAxis2 = new CategoryAxis();
    xAxis2.setLabel("X");

    BarChart<String, Number> barChart = new BarChart<>(xAxis2, yAxis);
    barChart.setLegendVisible(false);
    barChart.setAnimated(false);
    //barChart.setAlternativeRowFillVisible(false);
    //barChart.setAlternativeColumnFillVisible(false);
    //barChart.setHorizontalGridLinesVisible(false);
    //barChart.setVerticalGridLinesVisible(false);
    barChart.getXAxis().setVisible(false);
    barChart.getYAxis().setVisible(false);

    XYChart.Series<String, Number> barSeries = new XYChart.Series<>();
    barSeries.getData().add(new XYChart.Data<>("1", 2.4));
    barSeries.getData().add(new XYChart.Data<>("2", 2.7));
    barSeries.getData().add(new XYChart.Data<>("3", 0.8));
    barSeries.getData().add(new XYChart.Data<>("4", -3.2));
    barSeries.getData().add(new XYChart.Data<>("5", -0.1));

    barChart.getData().addAll(barSeries);
    barChart.getStylesheets().add("sample/BarChart.css");
    barChart.setPadding(new Insets(0,0,35,3));

    StackPane pane = new StackPane();
    pane.getChildren().addAll(lineChart, barChart);

Upvotes: 0

Views: 373

Answers (1)

findusl
findusl

Reputation: 2644

You can make your NumberAxis start at 0.5 and end at 5.5 then the tick marks will nearly overlap. Then you tell either the NumberAxis or the CategoryAxis not to show it's tick marks and it will be fitting.

If you don't want to change the range of the NumberAxis and you are ok with the numbers not being aligned to the values of the BarChart, you can simply tell the CategoryAxis not to show it's tick marks.

The function for that is setTickLabelsVisible(boolean) and probably you also should use setTickMarkVisible(boolean).

I didn't test this.

Upvotes: 0

Related Questions