35 散点图
本章介绍散点图,它是一个二维坐标图,将数据呈现为一组点。
每个点由X和Y值定义。与其他二维坐标图一样,您可以创建一个或多个数据系列。 图35-1展示了一个包含三个数据系列的散点图。
创建散点图
要创建散点图,需要定义至少一个数据系列,设置水平和垂直轴,通过实例化ScatterChart类来创建图表,并将数据分配给图表。示例35-1演示了如何创建一个包含两个数据系列的简单散点图。
示例35-1 包含两个数据系列的散点图
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.ScatterChart;
import javafx.scene.chart.XYChart;
import javafx.stage.Stage;
public class ScatterChartSample extends Application {
@Override public void start(Stage stage) {
stage.setTitle("散点图示例");
final NumberAxis xAxis = new NumberAxis(0, 10, 1);
final NumberAxis yAxis = new NumberAxis(-100, 500, 100);
final ScatterChart<Number,Number> sc = new
ScatterChart<>(xAxis,yAxis);
xAxis.setLabel("年龄(岁)");
yAxis.setLabel("累计回报");
sc.setTitle("投资概览");
XYChart.Series series1 = new XYChart.Series();
series1.setName("股票");
series1.getData().add(new XYChart.Data(4.2, 193.2));
series1.getData().add(new XYChart.Data(2.8, 33.6));
series1.getData().add(new XYChart.Data(6.2, 24.8));
series1.getData().add(new XYChart.Data(1, 14));
series1.getData().add(new XYChart.Data(1.2, 26.4));
series1.getData().add(new XYChart.Data(4.4, 114.4));
series1.getData().add(new XYChart.Data(8.5, 323));
series1.getData().add(new XYChart.Data(6.9, 289.8));
series1.getData().add(new XYChart.Data(9.9, 287.1));
series1.getData().add(new XYChart.Data(0.9, -9));
series1.getData().add(new XYChart.Data(3.2, 150.8));
series1.getData().add(new XYChart.Data(4.8, 20.8));
series1.getData().add(new XYChart.Data(7.3, -42.3));
series1.getData().add(new XYChart.Data(1.8, 81.4));
series1.getData().add(new XYChart.Data(7.3, 110.3));
series1.getData().add(new XYChart.Data(2.7, 41.2));
XYChart.Series series2 = new XYChart.Series();
series2.setName("共同基金");
series2.getData().add(new XYChart.Data(5.2, 229.2));
series2.getData().add(new XYChart.Data(2.4, 37.6));
series2.getData().add(new XYChart.Data(3.2, 49.8));
series2.getData().add(new XYChart.Data(1.8, 134));
series2.getData().add(new XYChart.Data(3.2, 236.2));
series2.getData().add(new XYChart.Data(7.4, 114.1));
series2.getData().add(new XYChart.Data(3.5, 323));
series2.getData().add(new XYChart.Data(9.3, 29.9));
series2.getData().add(new XYChart.Data(8.1, 287.4));
sc.getData().addAll(series1, series2);
Scene scene = new Scene(sc, 500, 400);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
在这个例子中,ScatterChart对象使用两个Number轴来展示年份和回报金额的数值数据。数据的范围和刻度单位在NumberAxis类的构造函数中定义。
编译和运行这个应用程序的结果如图35-2所示。
管理图表数据
示例35-1创建了一个散点图,其数据被编码到应用程序中,无法从用户界面更改。在应用程序中使用UI控件来管理图表呈现的数据集,例如添加和删除一系列数据。
查看示例35-2中的代码。它创建了两个按钮,添加系列和删除系列,以改变数据集。
示例35-2 使用按钮管理图表数据
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.ScatterChart;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ScatterChartSample extends Application {
@Override public void start(Stage stage) {
stage.setTitle("散点图示例");
final NumberAxis xAxis = new NumberAxis(0, 10, 1);
final NumberAxis yAxis = new NumberAxis(-100, 500, 100);
final ScatterChart<Number,Number> sc =
new ScatterChart<>(xAxis,yAxis);
xAxis.setLabel("年龄(岁)");
yAxis.setLabel("累计回报");
sc.setTitle("投资概览");
XYChart.Series series1 = new XYChart.Series();
series1.setName("选项1");
series1.getData().add(new XYChart.Data(4.2, 193.2));
series1.getData().add(new XYChart.Data(2.8, 33.6));
series1.getData().add(new XYChart.Data(6.2, 24.8));
series1.getData().add(new XYChart.Data(1, 14));
series1.getData().add(new XYChart.Data(1.2, 26.4));
series1.getData().add(new XYChart.Data(4.4, 114.4));
series1.getData().add(new XYChart.Data(8.5, 323));
series1.getData().add(new XYChart.Data(6.9, 289.8));
series1.getData().add(new XYChart.Data(9.9, 287.1));
series1.getData().add(new XYChart.Data(0.9, -9));
series1.getData().add(new XYChart.Data(3.2, 150.8));
series1.getData().add(new XYChart.Data(4.8, 20.8));
series1.getData().add(new XYChart.Data(7.3, -42.3));
series1.getData().add(new XYChart.Data(1.8, 81.4));
series1.getData().add(new XYChart.Data(7.3, 110.3));
series1.getData().add(new XYChart.Data(2.7, 41.2));
sc.setPrefSize(500, 400);
sc.getData().addAll(series1);
Scene scene = new Scene(new Group());
final VBox vbox = new VBox();
final HBox hbox = new HBox();
final Button add = new Button("添加系列");
final Button remove = new Button("删除系列");
hbox.setSpacing(10);
hbox.getChildren().addAll(add, remove);
vbox.getChildren().addAll(sc, hbox);
hbox.setPadding(new Insets(10, 10, 10, 50));
((Group)scene.getRoot()).getChildren().add(vbox);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
与示例35-1直接将散点图添加到场景不同,示例35-2使用VBox和HBox布局容器来排列应用场景中的组件。
如示例35-3所示,为“添加系列”按钮定义setOnAction方法。它通过使用随机计算的值填充XYChart.Series对象来创建新的数据系列。每个新系列都使用add(series)方法分配给图表。
示例35-3 添加数据系列
add.setOnAction((ActionEvent e) -> {
if (sc.getData() == null) {
sc.setData(FXCollections.<XYChart.Series<Number,
Number>>observableArrayList());
}
ScatterChart.Series<Number, Number> series
= new ScatterChart.Series<>();
series.setName("选项 " + (sc.getData().size() + 1));
for (int i = 0; i < 100; i++) {
series.getData().add(
new ScatterChart.Data<>(Math.random() * 100,
Math.random() * 500));
}
sc.getData().add(series);
});
要从图表中删除数据系列,如示例35-4所示,为“删除系列”按钮定义setOnAction方法。散点图上调用的remove(int)方法通过使用随机生成的索引来删除数据系列。
示例35-4 删除数据系列
remove.setOnAction((ActionEvent e) -> {
if (!sc.getData().isEmpty())
sc.getData().remove((int)(
Math.random()*(sc.getData().size()-1)));
});
当将示例35-3和示例35-4添加到示例35-2中的应用程序中时,将显示图35-3中的输出。它捕捉了将五个系列添加到“选项1”系列的时刻。
用于表示一系列数据的符号被编码到ScatterChart类的实现中。 示例35-5显示了散点图符号的默认样式。
示例35-5 设置散点图符号的样式
.default-color5.chart-symbol { /* 空心圆 */
-fx-background-color: #860061, white;
-fx-background-insets: 0, 2;
-fx-background-radius: 5px;
-fx-padding: 5px;
}
您可以通过设置.default-color5.chart-symbol属性的替代值来更改此符号的样式。有关更多信息,请参见使用CSS样式化图表。
向图表添加效果
javafx.scene.chart中的所有图表类都是Node类的扩展。因此,您可以对每种类型的图表应用视觉效果或变换。查看示例35-6中的代码片段。它创建并应用了一个投影效果到散点图。
示例35-6 创建并应用投影效果
final DropShadow shadow = new DropShadow(); shadow.setOffsetX(2); shadow.setColor(Color.GREY); sc.setEffect(shadow);
当您将此代码片段添加到投资概览应用程序中,然后编译并运行它,散点图将被阴影突出显示,如图35-4所示。
请注意,投影的视觉效果应用于图表的所有元素,包括轴、刻度线和刻度标签。
更改图表符号
散点图中的每个数据系列都由modena.css中定义的符号表示,这是JavaFX应用程序的默认样式表。但是,您可以通过实现自己的样式表来更改图表符号。
创建Chart.css文件,并将其保存在AreaChartSample应用程序的主类所在的同一目录中。将示例35-7中显示的行添加到Chart.css文件中。
示例35-7 使用CSS创建新的图表符号
.chart-symbol{
-fx-stroke: #a9e200;
-fx-shape: "M0,4 L2,4 L4,8 L7,0 L9,0 L4,11 Z";
}
此代码片段通过在-fx-shape参数中定义其SVG路径来创建符号形状,并为符号设置描边颜色。
使用Scene类的getStylesheets()方法将样式表应用于应用程序,如示例35-8所示。
编译并运行此应用程序将产生修改后的面积图的外观,如图35-5所示。
您可以从使用CSS样式的JavaFX应用程序和使用CSS样式的UI控件中了解更多关于在JavaFX应用程序中使用CSS样式的信息。
相关API文档

