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);
我在 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);