32 折线图
本章介绍了折线图,一种将数据以一系列通过直线连接的点来呈现的双轴图表类型。
折线图通常用于展示特定时间间隔内数据的动态变化。图32-1展示了一个具有三个数据系列的典型折线图。
每个双轴图表都有两个轴、数据点的绘制和图例。您还可以为图表指定一个标题。
图表设置
对于每个图表,您可以指定标题及其相对于图表的位置。标题可以位于图表的顶部、右侧、左侧或底部。同样,您可以指定图表图例的位置。
对于双轴图表,您可以管理图表绘制的外观,即数据值对应的图形符号所呈现的图表区域。您可以设置替代列和行,水平和垂直网格线以及零线。
您可以通过定义以下设置来更改每个图表的默认外观:
-
轴标签
-
轴相对于图表绘制的位置
-
轴范围的上下边界
-
刻度线的最小和最大刻度、刻度线之间的间隔以及刻度标签
您还可以指定对轴及其范围的任何更改都将进行动画处理,或者可以启用轴自动根据数据确定其范围。
图表数据
XYChart
类是所有双轴图表的超类,提供了构建面积图、折线图、柱状图、散点图和气泡图的基本功能。使用XYChart.Data
类来指定这些类型图表的数据模型。xValue
属性定义要在X轴上绘制的图表元素的值,yValue
属性定义Y轴的值。您还可以为每个图表元素设置额外的值。该值可以以图表需要的任何方式绘制,或者可以用于存储有关图表元素的附加信息。例如,它可以用于定义气泡图的半径。
对于双轴图表,您可以使用XYChart.Series
类定义多个数据系列。您还可以为每个系列分配一个特定的名称以在图表图例中显示。
创建折线图
要创建折线图,至少需要定义两个轴,通过实例化LineChart
类创建LineChart
对象,使用XYChart.Series
类创建一个或多个数据系列,并将数据分配给图表。示例32-1实现了这些任务。
示例32-1 简单折线图
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.chart.LineChart; import javafx.scene.chart.NumberAxis; import javafx.scene.chart.XYChart; import javafx.stage.Stage; public class LineChartSample extends Application { @Override public void start(Stage stage) { stage.setTitle("折线图示例"); //定义轴 final NumberAxis xAxis = new NumberAxis(); final NumberAxis yAxis = new NumberAxis(); xAxis.setLabel("月份"); //创建图表 final LineChart<Number,Number> lineChart = new LineChart<Number,Number>(xAxis,yAxis); lineChart.setTitle("股票监控, 2010"); //定义数据系列 XYChart.Series series = new XYChart.Series(); series.setName("我的投资组合"); //填充数据系列 series.getData().add(new XYChart.Data(1, 23)); series.getData().add(new XYChart.Data(2, 14)); series.getData().add(new XYChart.Data(3, 15)); series.getData().add(new XYChart.Data(4, 24)); series.getData().add(new XYChart.Data(5, 34)); series.getData().add(new XYChart.Data(6, 36)); series.getData().add(new XYChart.Data(7, 22)); series.getData().add(new XYChart.Data(8, 45)); series.getData().add(new XYChart.Data(9, 43)); series.getData().add(new XYChart.Data(10, 17)); series.getData().add(new XYChart.Data(11, 29)); series.getData().add(new XYChart.Data(12, 25)); Scene scene = new Scene(lineChart,800,600); lineChart.getData().add(series); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }
在这个示例中,使用NumberAxis
类创建了垂直和水平轴,NumberAxis
类是Axis
类的子类,用于表示数值。在创建数据系列时,由于已经声明了X
轴和Y
轴是数值类型,因此在创建XYChart.Data
对象时应指定Number
参数。XYChart.Data
对象的第一个参数定义了水平轴的值,而第二个参数定义了垂直轴的值。
编译和运行此应用程序的结果如图32-2所示。
在图32-2中显示的折线图使用符号突出显示图表上的每个数据项。如果您想在折线图上显示趋势而不是具体的数据值,可以禁用图表符号,如示例32-2所示。
趋势图的示例显示在图32-1中。
在图32-1中,坐标轴显示在其相对于图表绘图的默认位置。但是,您可以通过应用setSide
方法将坐标轴显示在图表绘图的另一侧。 示例32-3演示了如何将水平轴移动到图表绘图的顶部。
创建线图的类别
使用CategoryAxis
类而不是NumberAxis
类来在线图中呈现非数字数据。
查看示例32-4中显示的应用程序的修改代码。它通过实例化CategoryAxis
类来创建水平轴。修改了LineChart
对象的声明以适应X轴类型的更改。
示例32-4 使用类别轴显示月份
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.chart.CategoryAxis; import javafx.scene.chart.LineChart; import javafx.scene.chart.NumberAxis; import javafx.scene.chart.XYChart; import javafx.stage.Stage; public class LineChartSample extends Application { @Override public void start(Stage stage) { stage.setTitle("线图示例"); final CategoryAxis xAxis = new CategoryAxis(); final NumberAxis yAxis = new NumberAxis(); xAxis.setLabel("月份"); final LineChart<String,Number> lineChart = new LineChart<String,Number>(xAxis,yAxis); lineChart.setTitle("股票监控, 2010"); XYChart.Series series = new XYChart.Series(); series.setName("我的投资组合"); series.getData().add(new XYChart.Data("一月", 23)); series.getData().add(new XYChart.Data("二月", 14)); series.getData().add(new XYChart.Data("三月", 15)); series.getData().add(new XYChart.Data("四月", 24)); series.getData().add(new XYChart.Data("五月", 34)); series.getData().add(new XYChart.Data("六月", 36)); series.getData().add(new XYChart.Data("七月", 22)); series.getData().add(new XYChart.Data("八月", 45)); series.getData().add(new XYChart.Data("九月", 43)); series.getData().add(new XYChart.Data("十月", 17)); series.getData().add(new XYChart.Data("十一月", 29)); series.getData().add(new XYChart.Data("十二月", 25)); Scene scene = new Scene(lineChart,800,600); lineChart.getData().add(series); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }
XYChartData
对象包含月份名称和相应的数值。水平轴的标签会相应地进行修改。
编译和运行修改后的应用程序的结果如图32-3所示。
通常,线图可以在同一时间段内分析不同的数据集。在应用程序中使用多个XYChart.Data
对象系列来实现这个任务。
向折线图添加系列
示例32-5提供了带有三个数据系列的股票监控应用程序的源代码。除了示例32-4中使用的系列之外,还声明了两个新的系列。
通过连续调用getData
和addAll
方法将系列分配给图表。
示例 32-5 向股票监控示例中添加两个系列
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.chart.CategoryAxis; import javafx.scene.chart.LineChart; import javafx.scene.chart.NumberAxis; import javafx.scene.chart.XYChart; import javafx.stage.Stage; public class LineChartSample extends Application { @Override public void start(Stage stage) { stage.setTitle("折线图示例"); final CategoryAxis xAxis = new CategoryAxis(); final NumberAxis yAxis = new NumberAxis(); xAxis.setLabel("月份"); final LineChart<String,Number> lineChart = new LineChart<String,Number>(xAxis,yAxis); lineChart.setTitle("股票监控, 2010"); XYChart.Series series1 = new XYChart.Series(); series1.setName("投资组合 1"); series1.getData().add(new XYChart.Data("一月", 23)); series1.getData().add(new XYChart.Data("二月", 14)); series1.getData().add(new XYChart.Data("三月", 15)); series1.getData().add(new XYChart.Data("四月", 24)); series1.getData().add(new XYChart.Data("五月", 34)); series1.getData().add(new XYChart.Data("六月", 36)); series1.getData().add(new XYChart.Data("七月", 22)); series1.getData().add(new XYChart.Data("八月", 45)); series1.getData().add(new XYChart.Data("九月", 43)); series1.getData().add(new XYChart.Data("十月", 17)); series1.getData().add(new XYChart.Data("十一月", 29)); series1.getData().add(new XYChart.Data("十二月", 25)); XYChart.Series series2 = new XYChart.Series(); series2.setName("投资组合 2"); series2.getData().add(new XYChart.Data("一月", 33)); series2.getData().add(new XYChart.Data("二月", 34)); series2.getData().add(new XYChart.Data("三月", 25)); series2.getData().add(new XYChart.Data("四月", 44)); series2.getData().add(new XYChart.Data("五月", 39)); series2.getData().add(new XYChart.Data("六月", 16)); series2.getData().add(new XYChart.Data("七月", 55)); series2.getData().add(new XYChart.Data("八月", 54)); series2.getData().add(new XYChart.Data("九月", 48)); series2.getData().add(new XYChart.Data("十月", 27)); series2.getData().add(new XYChart.Data("十一月", 37)); series2.getData().add(new XYChart.Data("十二月", 29)); XYChart.Series series3 = new XYChart.Series(); series3.setName("投资组合 3"); series3.getData().add(new XYChart.Data("一月", 44)); series3.getData().add(new XYChart.Data("二月", 35)); series3.getData().add(new XYChart.Data("三月", 36)); series3.getData().add(new XYChart.Data("四月", 33)); series3.getData().add(new XYChart.Data("五月", 31)); series3.getData().add(new XYChart.Data("六月", 26)); series3.getData().add(new XYChart.Data("七月", 22)); series3.getData().add(new XYChart.Data("八月", 25)); series3.getData().add(new XYChart.Data("九月", 43)); series3.getData().add(new XYChart.Data("十月", 44)); series3.getData().add(new XYChart.Data("十一月", 45)); series3.getData().add(new XYChart.Data("十二月", 44)); Scene scene = new Scene(lineChart,800,600); lineChart.getData().addAll(series1, series2, series3); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }
每个数据系列都有一个唯一的名称,可以使用setName
方法来定义。
编译和运行此应用程序的结果如图32-4所示。
请注意,线条的不同颜色是由addAll
方法中相应系列的声明顺序定义的。将顺序更改为:lineChart.getData().addAll(series3, series1, series2)
,然后编译和运行应用程序。修改后的输出如图32-5所示。
相关API文档