JavaFX 中的堆叠图表

Stacking charts in JavaFX

我在 JavaFX 中使用条形图和折线图。当我将两个图表制作成相同大小并将它们放在同一位置时,它们彼此完美重叠。我将如何使 LineChart 出现在 BarChart 之上。

目前我将不透明度设置为 0.7,因此它们 'look good' 但显然这不是正确的方法。

Jewelsea 发布了 example on a gist

基本上归结为使用 StackPane 来堆叠图表并修改所有叠加层的可见性。

这是我如何使用它的更简单的修改版本:

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;
}

我没有足够的 "reputation" 在 Roland 的回答下添加评论,但我担心提议的解决方案存在问题。

1)如果第2个系列的值不一样,y轴适配它们的范围,第1个图表高度不适应

以下示例:第一个橙色条的值为 25,601:它应该矮一些。

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) 一个解决办法是从头设置y轴的边界:

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