文档



JavaFX:使用JavaFX UI组件

35 散点图

本章介绍散点图,它是一个二维坐标图,将数据呈现为一组点。

每个点由X和Y值定义。与其他二维坐标图一样,您可以创建一个或多个数据系列。 图35-1展示了一个包含三个数据系列的散点图。

图35-1 散点图示例

图35-1的描述如下
"图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-2 展示投资概览的散点图

图35-2的描述如下
"图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使用VBoxHBox布局容器来排列应用场景中的组件。

示例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”系列的时刻。

图35-3 添加的数据系列

图35-3的描述
图35-3的描述

用于表示一系列数据的符号被编码到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所示。

图35-4 带有投影的散点图

图35-4的描述
"图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-8 将CSS样式应用于场景

scene.getStylesheets().add("scaterchartsample/Chart.css");

编译并运行此应用程序将产生修改后的面积图的外观,如图35-5所示。

图35-5 带有修改后图表符号的散点图

图35-5的描述
"图35-5 带有修改后图表符号的散点图"的描述

您可以从使用CSS样式的JavaFX应用程序使用CSS样式的UI控件中了解更多关于在JavaFX应用程序中使用CSS样式的信息。

相关API文档 

关闭窗口

目录

JavaFX:使用JavaFX UI组件

展开 折叠