原文地址:DOC-03-33 面积图(Area Chart) | JavaFX中文资料
与折线图类似,面积图用直线连接的一组点来表示数据。但是,坐标轴和连线之间的区域是带有颜色的。每一组数据都会用不同的颜色来绘制。
要在你的程序中创建一个简单的面积图,你至少需要定义两个坐标轴、通过实例化AreaChart类来创建AreaChart对象、使用XYChart.Series类创建一组或多组数据并且将数据分配给图表。
实例化AreaChart类时,你可以在构造方法中指定一组数据,或者也可以在实例化以后通过调用AreaChart对象的getData和addAll方法来增加数据
/** * @author zhaoyong * @Date 2022/4/29 * @Description 面积图 */ import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.chart.AreaChart; import javafx.scene.chart.NumberAxis; import javafx.scene.chart.XYChart; import javafx.stage.Stage; public class AreaChartSample extends Application { @Override public void start(Stage stage) { stage.setTitle("面积图例子"); final NumberAxis xAxis = new NumberAxis(1, 31, 1);//x轴定义是一个数字轴 final NumberAxis yAxis = new NumberAxis();//定义y轴也是个数字轴 final AreaChart<Number,Number> ac = new AreaChart<>(xAxis,yAxis);//创建一个面积图 ac.setTitle("温度监控");//给面积图加标题 XYChart.Series seriesApril= new XYChart.Series();//创建一个数据序列 seriesApril.setName("5月份"); seriesApril.getData().add(new XYChart.Data(1, 4)); seriesApril.getData().add(new XYChart.Data(3, 10)); seriesApril.getData().add(new XYChart.Data(6, 15)); seriesApril.getData().add(new XYChart.Data(9, 8)); seriesApril.getData().add(new XYChart.Data(12, 5)); seriesApril.getData().add(new XYChart.Data(15, 18)); seriesApril.getData().add(new XYChart.Data(18, 15)); seriesApril.getData().add(new XYChart.Data(21, 13)); seriesApril.getData().add(new XYChart.Data(24, 19)); seriesApril.getData().add(new XYChart.Data(27, 21)); seriesApril.getData().add(new XYChart.Data(30, 21)); XYChart.Series seriesMay = new XYChart.Series();//创建一个数据序列 seriesMay.setName("6月份"); seriesMay.getData().add(new XYChart.Data(1, 20)); seriesMay.getData().add(new XYChart.Data(3, 15)); seriesMay.getData().add(new XYChart.Data(6, 13)); seriesMay.getData().add(new XYChart.Data(9, 12)); seriesMay.getData().add(new XYChart.Data(12, 14)); seriesMay.getData().add(new XYChart.Data(15, 18)); seriesMay.getData().add(new XYChart.Data(18, 25)); seriesMay.getData().add(new XYChart.Data(21, 25)); seriesMay.getData().add(new XYChart.Data(24, 23)); seriesMay.getData().add(new XYChart.Data(27, 26)); seriesMay.getData().add(new XYChart.Data(31, 26)); Scene scene = new Scene(ac,800,600);//创建场景 ac.getData().addAll(seriesApril, seriesMay);//面积图的数据区域添加数据序列 stage.setScene(scene);//舞台设置场景 stage.show();//舞台展现 } public static void main(String[] args) { launch(null);//开启程序 } }
该示例创建了两个NumberAxis对象来表示带有数值的横轴和纵轴。横轴(X轴)的数据来自于XYChart.Data对象的第一个参数,而第二个参数则提供了Y轴的数据。
将数据序列分配给图表可通过调用getData和addAll方法来完成。
————————————————————————————————————————
创建堆积(Stacked)面积图
在面积图中可以通过使用StackedAreaChart类来表示数据。这个类创建的区域是堆叠起来的,因此每组数据区域会相邻而不会覆盖之前的数据区域
/** * @author zhaoyong * @Date 2022/4/29 * @Description 面积图 */ import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.chart.NumberAxis; import javafx.scene.chart.StackedAreaChart; import javafx.scene.chart.XYChart; import javafx.stage.Stage; public class StackedAreaChartSample extends Application { final NumberAxis xAxis = new NumberAxis(1, 31, 1); final NumberAxis yAxis = new NumberAxis(); final StackedAreaChart<Number, Number> sac = new StackedAreaChart<>(xAxis, yAxis);//堆栈面积图 @Override public void start(Stage stage) { stage.setTitle("面积图例子"); sac.setTitle("温度监控"); XYChart.Series<Number, Number> seriesApril = new XYChart.Series<>(); seriesApril.setName("四月"); seriesApril.getData().add(new XYChart.Data(1, 4)); seriesApril.getData().add(new XYChart.Data(3, 10)); seriesApril.getData().add(new XYChart.Data(6, 15)); seriesApril.getData().add(new XYChart.Data(9, 8)); seriesApril.getData().add(new XYChart.Data(12, 5)); seriesApril.getData().add(new XYChart.Data(15, 18)); seriesApril.getData().add(new XYChart.Data(18, 15)); seriesApril.getData().add(new XYChart.Data(21, 13)); seriesApril.getData().add(new XYChart.Data(24, 19)); seriesApril.getData().add(new XYChart.Data(27, 21)); seriesApril.getData().add(new XYChart.Data(30, 21)); XYChart.Series<Number, Number> seriesMay = new XYChart.Series<>(); seriesMay.setName("5月"); seriesMay.getData().add(new XYChart.Data(1, 20)); seriesMay.getData().add(new XYChart.Data(3, 15)); seriesMay.getData().add(new XYChart.Data(6, 13)); seriesMay.getData().add(new XYChart.Data(9, 12)); seriesMay.getData().add(new XYChart.Data(12, 14)); seriesMay.getData().add(new XYChart.Data(15, 18)); seriesMay.getData().add(new XYChart.Data(18, 25)); seriesMay.getData().add(new XYChart.Data(21, 25)); seriesMay.getData().add(new XYChart.Data(24, 23)); seriesMay.getData().add(new XYChart.Data(27, 26)); seriesMay.getData().add(new XYChart.Data(31, 26)); Scene scene = new Scene(sac, 800, 600); sac.getData().addAll(seriesApril, seriesMay); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }
通过比较图 相同的数据可知,在堆积面积图中,显示的是在横轴给定的点上纵轴上的累加值。例如,堆积面积图中5月15日的纵轴数据值是36,与当天的实际温度并不相符。该值表示4月15日和5月15日温度的累加结果。
当你在你的程序中开发面积图时,要记得使用不同类型的面积图(AreaChart或者StackedAreaChart)时,纵轴上的数据表示的含义是不同的。要根据程序目标选择最恰当的数据表示方式
设置坐标轴和刻度的属性
温度监控程序的输出表示了坐标轴上的数值,该数值默认是double类型的,这种方式谈不上对用户友好。例如,每个月的天数应该是整数并且在1-31范围之内,而不应是浮点数。
JavaFX SDK的API提供了多种方法来调整图表坐标轴上的值的展现形式。图展示了图表坐标轴的主要元素,包括刻度线和刻度值,它们显示了刻度范围的数值。
你可以通过使用NumberAxis类的构造方法或对应的方法指定数值区间的最小值和最大值
//Using the NumberAxis constructor
final NumberAxis xAxis = new NumberAxis(1, 31, 1);
//Using the corresponding methods
xAxis.setLowerBound(1);
xAxis.setUpperBound(31);
xAxis.setTickUnit(1);
在使用NumberAxis类的带有3个参数的构造方法来设置数值时,要记得第一个参数表示数值范围的最小值,第二个参数表示数值范围的最大值,第三个参数表示刻度单元,也就是在坐标轴上两个刻度之间的差值。
另外,如果你想要禁止显示横轴上的次刻度线(Minor tick mark),可以把minorTickCount属性设置为0,如例33-4所示。
将次刻度线数量设置为0
Java
1 | xAxis.setMinorTickCount(0); |
该属性定义了显示在每个主刻度线之间的次刻度线的数量。通过把这个值设置为0,你就屏蔽了横轴的次刻度线。
如果你的程序不想要显示刻度值,使用setTickLabelsVisible方法并设置参数值为false即可。类似的,使用setTickMarkVisible方法并设置参数值为false可以将刻度线隐藏。
调整纵轴的值范围。
例 为纵轴指定数据范围
1 | final NumberAxis yAxis = new NumberAxis(0, 27, 5); |
通过使用tickLength和minorTickLength属性,你可以调整刻度线以使主刻度线和次刻度线长度相同
调整主次刻度线的长度
1 | yAxis.setMinorTickLength(yAxis.getTickLength()); |
纵轴发生的变化
增加负值
因为温度监控程序的纵轴是由NumberAxis类创建的,所以你可以为该面积图的数据设置负值
/** * @author zhaoyong * @Date 2022/5/11 * @Description */ import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.chart.AreaChart; import javafx.scene.chart.NumberAxis; import javafx.scene.chart.XYChart; import javafx.stage.Stage; public class AreaChartTest extends Application { @Override public void start(Stage stage) { stage.setTitle("区域图例子");// final NumberAxis xAxis = new NumberAxis(1, 31, 1);//设置一个x轴三个参数是:最小值,最大值,刻度单位长 xAxis.setMinorTickCount(0);//将次刻度线数量设置为0 final NumberAxis yAxis = new NumberAxis(-5, 27, 5);//设置一个y轴三个参数是:最小值,最大值,刻度单位长 yAxis.setMinorTickLength(yAxis.getTickLength());//设置次刻度线数量 yAxis.setForceZeroInRange(false); final AreaChart<Number,Number> ac = new AreaChart<Number,Number>(xAxis,yAxis);// 创建一个区域图 ac.setTitle("温度监控");//设置图的标题 XYChart.Series seriesApril= new XYChart.Series();//创建图的数据序列对象(最后会形成一条线区间) seriesApril.setName("4月"); seriesApril.getData().add(new XYChart.Data(0, 4));//画出图的数据序列坐标(x轴值,y轴值)相当于确定一个数据点 seriesApril.getData().add(new XYChart.Data(3, 10)); seriesApril.getData().add(new XYChart.Data(6, 15)); seriesApril.getData().add(new XYChart.Data(9, 8)); seriesApril.getData().add(new XYChart.Data(12, 5)); seriesApril.getData().add(new XYChart.Data(15, 18)); seriesApril.getData().add(new XYChart.Data(18, 15)); seriesApril.getData().add(new XYChart.Data(21, 13)); seriesApril.getData().add(new XYChart.Data(24, 19)); seriesApril.getData().add(new XYChart.Data(27, 21)); seriesApril.getData().add(new XYChart.Data(30, 21));//画出图的数据序列坐标(x轴值,y轴值)相当于确定一个数据点 XYChart.Series seriesMay = new XYChart.Series();//创建一个数据序列对象 seriesMay.setName("5月"); seriesMay.getData().add(new XYChart.Data(0, 20)); seriesMay.getData().add(new XYChart.Data(3, 15)); seriesMay.getData().add(new XYChart.Data(6, 13)); seriesMay.getData().add(new XYChart.Data(9, 12)); seriesMay.getData().add(new XYChart.Data(12, 14)); seriesMay.getData().add(new XYChart.Data(15, 18)); seriesMay.getData().add(new XYChart.Data(18, 25)); seriesMay.getData().add(new XYChart.Data(21, 25)); seriesMay.getData().add(new XYChart.Data(24, 23)); seriesMay.getData().add(new XYChart.Data(27, 26)); seriesMay.getData().add(new XYChart.Data(31, 26)); XYChart.Series seriesMarch = new XYChart.Series();//创建一个数据序列对象 seriesMarch.setName("三月"); seriesMarch.getData().add(new XYChart.Data(0, -2)); seriesMarch.getData().add(new XYChart.Data(3, -4)); seriesMarch.getData().add(new XYChart.Data(6, 0)); seriesMarch.getData().add(new XYChart.Data(9, 5)); seriesMarch.getData().add(new XYChart.Data(12, -4)); seriesMarch.getData().add(new XYChart.Data(15, 6)); seriesMarch.getData().add(new XYChart.Data(18, 8)); seriesMarch.getData().add(new XYChart.Data(21, 14)); seriesMarch.getData().add(new XYChart.Data(24, 4)); seriesMarch.getData().add(new XYChart.Data(27, 6)); seriesMarch.getData().add(new XYChart.Data(31, 6)); Scene scene = new Scene(ac,800,600);//创建场景对象,上面挂载报告图对象 ac.getData().addAll(seriesMarch, seriesApril, seriesMay);//数据图对象上挂载前文定义的三个数据序列对象 stage.setScene(scene);//舞台挂载场景 stage.show();//舞台展现 } public static void main(String[] args) { launch(args);//启动javaFX程序 } }
为面积图添加样式
例中的每个月的颜色是由相应的各组数据在addAll方法中的声明顺序决定的。这就解释了为什么图中3月份的数据是黄色的。你可以通过CSS来设置AreaChart对象的颜色。
创建Chart.css文件并将它保存在AreaChartSample程序主类的相同目录下。将例中的代码加到Chart.css文件中。
面积图的CSS样式
Java
1 2 3 4 5 6 7 8 9 10 11 | .default-color0.chart-area-symbol { -fx-background-color: #e9967a, #ffa07a; } .default-color1.chart-area-symbol { -fx-background-color: #f0e68c, #fffacd; } .default-color2.chart-area-symbol { -fx-background-color: #dda0dd, #d8bfd855; } .default-color0.chart-series-area-line { -fx-stroke: #e9967a; } .default-color1.chart-series-area-line { -fx-stroke: #f0e68c; } .default-color2.chart-series-area-line { -fx-stroke: #dda0dd; } .default-color0.chart-series-area-fill { -fx-fill: #ffa07a55; } .default-color1.chart-series-area-fill { -fx-fill: #fffacd55; } .default-color2.chart-series-area-fill { -fx-fill: #d8bfd855; } |
名为chart-area-symbol的CSS类定义了一组特定数据的图例标识参数。例设置了图例中圆圈的内部颜色和外部颜色。
名为chart-series-area-line的CSS类定义了面积图中连线的参数。在这个例子中,chart-series-area-fill的CSS类目定义了各区域的颜色和透明度。
这些样式通过调用Scene类的getStylesheets方法来应用到AreaChartSample程序中,如例所示。
为Scene应用CSS样式
1 | scene.getStylesheets().add("areachartsample/Chart.css"); |
编译并运行此程序,将会产生如图所示的修改后的面积图外观。