Stacking charts in JavaFX

后端 未结 2 2069
清酒与你
清酒与你 2020-12-03 09:27

I\'m using a BarChart and a LineChart in JavaFX. When I make the two charts the same size and put them put at the same place they overlap eachother perfectly. How would I ma

相关标签:
2条回答
  • 2020-12-03 09:47

    Jewelsea posted an example on a gist.

    It basically comes down to using a StackPane for stacking the charts and modifying the visibility of all the overlays.

    Here's a simpler modified version how I use it:

    public class StackedChartSample extends Application {
    
        final static String austria = "Austria";
        final static String brazil = "Brazil";
        final static String france = "France";
        final static String italy = "Italy";
        final static String usa = "USA";
    
        @Override
        public void start(Stage stage) {
    
            final CategoryAxis xAxis = new CategoryAxis();
            final NumberAxis yAxis = new NumberAxis();
    
            // base chart
            final BarChart<String, Number> barChart = new BarChart<String, Number>(xAxis, yAxis);
            barChart.setLegendVisible(false);
            barChart.setAnimated(false);
    
            xAxis.setLabel("Country");
            yAxis.setLabel("Value");
    
            // overlay chart
            LineChart<String, Number> lineChart = new LineChart<String, Number>(xAxis, yAxis);
            lineChart.setLegendVisible(false);
            lineChart.setAnimated(false);
            lineChart.setCreateSymbols(true);
            lineChart.setAlternativeRowFillVisible(false);
            lineChart.setAlternativeColumnFillVisible(false);
            lineChart.setHorizontalGridLinesVisible(false);
            lineChart.setVerticalGridLinesVisible(false);
            lineChart.getXAxis().setVisible(false);
            lineChart.getYAxis().setVisible(false);
            lineChart.getStylesheets().addAll(getClass().getResource("chart.css").toExternalForm());
    
            barChart.getData().add( createChartSeries());
            lineChart.getData().add( createChartSeries());
    
            StackPane root = new StackPane();
            root.getChildren().addAll( barChart, lineChart);
    
            Scene scene = new Scene(root, 800, 600);
    
            stage.setScene(scene);
            stage.show();
        }
    
        private XYChart.Series<String,Number> createChartSeries() {
    
            XYChart.Series<String,Number> series = new XYChart.Series<String,Number>();
            series.getData().add(new XYChart.Data<String,Number>(austria, 25601.34));
            series.getData().add(new XYChart.Data<String,Number>(brazil, 20148.82));
            series.getData().add(new XYChart.Data<String,Number>(france, 10000));
            series.getData().add(new XYChart.Data<String,Number>(italy, 35407.15));
            series.getData().add(new XYChart.Data<String,Number>(usa, 12000));
    
            return series;
        }
    
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    chart.css

    .chart-plot-background {
    -fx-background-color: transparent;
    }
    .default-color0.chart-series-line {
    -fx-stroke: blue;
    } 
    .default-color0.chart-line-symbol { 
        -fx-background-color: blue, white;
    }
    
    0 讨论(0)
  • 2020-12-03 10:09

    I do not have enough "reputation" to add a comment below Roland's answer, but I fear that there is an issue with the proposed solution.

    1) If the values of the 2nd series are not the same, the y-axis adapts to their range, but the 1st chart does not adapt in height.

    Example below: the value of the first orange bar is 25,601: it should be less tall.

    import javafx.application.Application;
    import javafx.scene.Scene;
    import javafx.scene.chart.BarChart;
    import javafx.scene.chart.CategoryAxis;
    import javafx.scene.chart.LineChart;
    import javafx.scene.chart.NumberAxis;
    import javafx.scene.chart.XYChart;
    import javafx.scene.layout.StackPane;
    import javafx.stage.Stage;
    
    public class Exemple158_JavaFX_Overlaid_Stacked_Charts extends Application {
    
    final static String AUSTRIA = "Austria";
    final static String BRAZIL = "Brazil";
    final static String FRANCE = "France";
    final static String ITALY = "Italy";
    final static String USA = "USA";
    
    
    @Override
    public void start(Stage stage) {
    
        // x-axis and y-axis  for both charts:
        final CategoryAxis xAxis = new CategoryAxis();
        xAxis.setLabel("Country");
        final NumberAxis yAxis1 = new NumberAxis();
        yAxis1.setLabel("Value");
    
        // first chart:
        final BarChart<String, Number> barChart = new BarChart<>(xAxis, yAxis1);
        barChart.setLegendVisible(false);
        barChart.setAnimated(false);
        XYChart.Series<String, Number> series1 = new XYChart.Series<>();
        series1.getData().add(new XYChart.Data<>(AUSTRIA, 25601.34));
        series1.getData().add(new XYChart.Data<>(BRAZIL, 20148.82));
        series1.getData().add(new XYChart.Data<>(FRANCE, 10000));
        series1.getData().add(new XYChart.Data<>(ITALY, 35407.15));
        series1.getData().add(new XYChart.Data<>(USA, 12000));
        barChart.getData().add(series1);
    
        // second chart (overlaid):
        final LineChart<String, Number> lineChart = new LineChart<>(xAxis, yAxis1);
        lineChart.setLegendVisible(false);
        lineChart.setAnimated(false);
        lineChart.setCreateSymbols(true);
        lineChart.setAlternativeRowFillVisible(false);
        lineChart.setAlternativeColumnFillVisible(false);
        lineChart.setHorizontalGridLinesVisible(false);
        lineChart.setVerticalGridLinesVisible(false);
        lineChart.getXAxis().setVisible(false);
        lineChart.getYAxis().setVisible(false);
        lineChart.getStylesheets().addAll(getClass().getResource("Exemple158.css").toExternalForm());
        XYChart.Series<String, Number> series2 = new XYChart.Series<>();
        int delta = 10000;
        series2.getData().add(new XYChart.Data<>(AUSTRIA, 25601.34 + delta));
        series2.getData().add(new XYChart.Data<>(BRAZIL, 20148.82 + delta));
        series2.getData().add(new XYChart.Data<>(FRANCE, 10000 + delta));
        series2.getData().add(new XYChart.Data<>(ITALY, 35407.15 + delta));
        series2.getData().add(new XYChart.Data<>(USA, 12000 + delta));
        lineChart.getData().add(series2);
    
        StackPane root = new StackPane();
        root.getChildren().addAll(barChart, lineChart);
        Scene scene = new Scene(root, 800, 600);
        stage.setScene(scene);
        stage.show();
    }
    
    public static void main(String[] args) {
        launch(args);
    }
    }
    

    CSS:

    .chart-plot-background {
    -fx-background-color: transparent;
    }
    
    .default-color0.chart-series-line {
    -fx-stroke: blue;
    }
    
    .default-color0.chart-line-symbol { 
    -fx-background-color: blue, white;
    }
    

    2) A solution is to set the bounds of the y-axis from the beginning:

    final NumberAxis yAxis1 = new NumberAxis(0, 48000, 5000);
    

    0 讨论(0)
提交回复
热议问题