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 make the LineChart appear to e on top of the BarChart.
For the moment I've been setting the opacity to 0.7 of them so they 'look good' but obviously that isn't the way to go.
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;
}
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);
来源:https://stackoverflow.com/questions/28788117/stacking-charts-in-javafx