JavaFX Charts Example
This is a JavaFX Charts Example. A chart is a graphical representation of data. Charts provide an easier way to analyze large volume of data visually. Typically, they are used for reporting purposes. Different types of charts exist. They differ in the way they represent the data. Not all types of charts are suitable for analyzing all types of data.
JavaFX supports charts, which can be integrated in a Java application. It contains a comprehensive, extensible Chart API that provides built-in support for several types of charts.
The following table shows an overview of the whole article:
Table Of Contents
The following examples uses Java SE 8 and JavaFX 2.2.
1. Introduction
1.1 The Chart API
The abstract Chart
is the base class for all charts. It inherits the Node class. Charts can be added to a Scene Graph. They can also be styled with CSS as any other nodes. The Chart
class contains properties and methods common to all type of charts.
JavaFX divides charts into two categories:
- Charts having no-axis
- Charts having an x-axis and a y-axis
The PieChart class falls into the first category. It has no axis, and it is used to draw a pie chart. The XYChart class falls into the second category. It is the abstract base class for all charts having two axes. Its subclasses, for example, LineChart, BarChart, etc., represent specific type of charts.
Every chart in JavaFX has three parts:
- A title
- A legend
- The Content
Different types of charts define their data differently. The Chart
class contains the following properties that are common to all types of charts:
- title
- titleSide
- legend
- legendSide
- legendVisible
- animated
The title
property specifies the title for a chart.
The titleSide
property specifies the location of the title. By default, the title is placed above the chart content. Its value is one of the constants of the Side enum: TOP
(default), RIGHT
, BOTTOM
and LEFT
. Typically, a chart uses different types of symbols to represent data in different categories.
A legend
lists symbols with their descriptions. The legend property is a Node and it specifies the legend for the chart. By default, a legend is placed below the chart content.
The legendSide
property specifies the location of the legend, which is one of the constants of the Side enum: TOP
, RIGHT
, BOTTOM
(default) and LEFT
.
The legendVisible
property specifies whether the legend is visible. By default, it is visible.
The animated
property specifies whether the change in the content of the chart is shown with some type of animation. By default, it is true.
1.2 Styling Charts with CSS
You can style all types of charts. The Chart class defines properties common to all types of charts. The default CSS style-class name for a chart is chart
. You can specify the legendSide
, legendVisible
, and titleSide
properties for all charts in a CSS as shown:
.chart { -fx-legend-side: top; -fx-legend-visible: true; -fx-title-side: bottom; }
Every chart defines two substructures:
- chart-title
- chart-content
The chart-title
is a Label and the chart-content
is a Pane. The following styles sets the background color for all charts to yellow and the title font to Arial 16px bold.
.chart-content { -fx-background-color: yellow; } .chart-title { -fx-font-family: "Aeial"; -fx-font-size: 16px; -fx-font-weight: bold; }
The default style-class name for legends is chart-legend
. The following style sets the legend background color to light gray.
.chart-legend { -fx-background-color: lightgray; }
Every legend has two substructures:
- chart-legend-item
- chart-legend-item-symbol
The chart-legend-item
is a Label, and it represents the text in the legend. The chart-legend-itemsymbol
is a Node
, and it represents the symbol next to the label, which is a circle by default. The following style sets the font size for the labels in legends to 10px and the legend symbols to an arrow.
.chart-legend-item { -fx-font-size: 16px; } .chart-legend-item-symbol { -fx-shape: "M0 -3.5 v7 l 4 -3.5z"; }
1.3 Using Data in Charts
FxChartUtil.java
import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.scene.chart.PieChart; import javafx.scene.chart.XYChart; public class FxChartUtil { // Create PieChart Data public static ObservableList<PieChart.Data> getChartData() { ObservableList<PieChart.Data> data = FXCollections. observableArrayList(); data.add(new PieChart.Data("China", 1275)); data.add(new PieChart.Data("India", 1017)); data.add(new PieChart.Data("Brazil", 172)); data.add(new PieChart.Data("UK", 59)); data.add(new PieChart.Data("USA", 285)); return data; } // Create XYChart Country Data public static ObservableList<XYChart.Series<Number, Number>> getCountrySeries() { XYChart.Series<Number, Number> seriesChina = new XYChart.Series<Number, Number>(); seriesChina.setName("China"); seriesChina.getData().add(new XYChart.Data<Number, Number>(1950, 555)); seriesChina.getData().add(new XYChart.Data<Number, Number>(2000, 1275)); seriesChina.getData().add(new XYChart.Data<Number, Number>(2050, 1395)); seriesChina.getData().add(new XYChart.Data<Number, Number>(2100, 1182)); seriesChina.getData().add(new XYChart.Data<Number, Number>(2150, 1149)); XYChart.Series<Number, Number> seriesIndia = new XYChart.Series<Number, Number>(); seriesIndia.setName("India"); seriesIndia.getData().add(new XYChart.Data<Number, Number>(1950, 358)); seriesIndia.getData().add(new XYChart.Data<Number, Number>(2000, 1017)); seriesIndia.getData().add(new XYChart.Data<Number, Number>(2050, 1531)); seriesIndia.getData().add(new XYChart.Data<Number, Number>(2100, 1458)); seriesIndia.getData().add(new XYChart.Data<Number, Number>(2150, 1308)); XYChart.Series<Number, Number> seriesUSA = new XYChart.Series<Number, Number>(); seriesUSA.setName("USA"); seriesUSA.getData().add(new XYChart.Data<Number, Number>(1950, 158)); seriesUSA.getData().add(new XYChart.Data<Number, Number>(2000, 285)); seriesUSA.getData().add(new XYChart.Data<Number, Number>(2050, 409)); seriesUSA.getData().add(new XYChart.Data<Number, Number>(2100, 437)); seriesUSA.getData().add(new XYChart.Data<Number, Number>(2150, 453)); ObservableList<XYChart.Series<Number, Number>> data = FXCollections.<XYChart.Series<Number, Number>>observableArrayList(); data.add(seriesChina); data.add(seriesIndia); data.add(seriesUSA); return data; } // Create XYChart Year Data public static ObservableList<XYChart.Series<String, Number>> getYearSeries() { XYChart.Series<String, Number> series1950 = new XYChart.Series<String, Number>(); series1950.setName("1950"); series1950.getData().add(new XYChart.Data<String, Number>("China", 555)); series1950.getData().add(new XYChart.Data<String, Number>("India", 358)); series1950.getData().add(new XYChart.Data<String, Number>("Brazil", 54)); series1950.getData().add(new XYChart.Data<String, Number>("UK", 50)); series1950.getData().add(new XYChart.Data<String, Number>("USA", 158)); XYChart.Series<String, Number> series2000 = new XYChart.Series<String, Number>(); series2000.setName("2000"); series2000.getData().add(new XYChart.Data<String, Number>("China", 1275)); series2000.getData().add(new XYChart.Data<String, Number>("India",1017)); series2000.getData().add(new XYChart.Data<String, Number>("Brazil", 172)); series2000.getData().add(new XYChart.Data<String, Number>("UK", 59)); series2000.getData().add(new XYChart.Data<String, Number>("USA", 285)); XYChart.Series<String, Number> series2050 = new XYChart.Series<String, Number>(); series2050.setName("2050"); series2050.getData().add(new XYChart.Data<String, Number>("China", 1395)); series2050.getData().add(new XYChart.Data<String, Number>("India",1531)); series2050.getData().add(new XYChart.Data<String, Number>("Brazil", 233)); series2050.getData().add(new XYChart.Data<String, Number>("UK", 66)); series2050.getData().add(new XYChart.Data<String, Number>("USA", 409)); ObservableList<XYChart.Series<String, Number>> data = FXCollections.<XYChart.Series<String, Number>>observableArrayList(); data.add(series1950); data.add(series2000); data.add(series2050); return data; } }
This is a Helper Class. The class consists of two static methods that generate
and return XYChart
data. The getCountrySeries()
method returns the list of series that plots the years along the x-axis and the corresponding populations along the y-axis. The getYearSeries()
method returns a list of series that plots the countries along the x-axis and the corresponding populations along the y-axis. Additionally, the class contains the method getChartData()
, which returns data for the PieChart
.
We will be calling these methods to get data for our PieChart
and XYCharts in subsequent sections.
2. The PieChart
2.1 The Code
FxChartsExample1.java
import javafx.application.Application; import javafx.collections.ObservableList; import javafx.geometry.Side; import javafx.scene.Scene; import javafx.scene.chart.PieChart; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class FxChartsExample1 extends Application { public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage stage) { // Create the PieChart PieChart chart = new PieChart(); // Set the Title of the Chart chart.setTitle("Population in Year 2000"); // Place the legend on the left side chart.setLegendSide(Side.LEFT); // Set the Data for the Chart ObservableList<PieChart.Data> chartData = FxChartUtil.getChartData(); chart.setData(chartData); // Create a Stackpane StackPane root = new StackPane(chart); // Set the Style-properties of the Pane root.setStyle("-fx-padding: 10;" + "-fx-border-style: solid inside;" + "-fx-border-width: 2;" + "-fx-border-insets: 5;" + "-fx-border-radius: 5;" + "-fx-border-color: blue;"); // Create the Scene Scene scene = new Scene(root); // Add the Stylesheet to the Scene scene.getStylesheets().add(getClass().getResource("piechart.css").toExternalForm()); // Add the Scene to the Stage stage.setScene(scene); // Set the Title of the Stage stage.setTitle("A Pie Chart Example"); // Display the Stage stage.show(); } }
A pie chart consists of a circle divided into sectors of different central angles. Typically, a pie is circular. The sectors are also known as pie pieces or pie slices. Each sector in the circle represents a quantity of some kind. The central angle of the area of a sector is proportional to the quantity it represents.
An instance of the PieChart
class represents a pie chart. The class contains two constructors:
- PieChart()
- PieChart(ObservableList<PieChart.Data> data)
The no-args constructor creates a pie chart with no content. You can add the content later using its data property. The second constructor creates a pie chart with the specified data as its content.
// Create the PieChart PieChart chart = new PieChart();
A slice in a pie chart is specified as an instance of the PieChart.Data
class. A slice has a name (or a label) and a pie value represented by the name
and pieValue
properties of the PieChart.Data
class, respectively.
The following statement creates a slice for a pie chart. The slice name is “China” and the pie value is 1275.
new PieChart.Data("China", 1275);
The content of a pie chart (all slices) is specified in an ObservableList<PieChart.Data>
.
The following snippet of code creates an ObservableList<PieChart.Data>
and adds the pie slices to it.
// Create PieChart Data public static ObservableList<PieChart.Data> getChartData() { ObservableList<PieChart.Data> data = FXCollections. observableArrayList(); data.add(new PieChart.Data("China", 1275)); data.add(new PieChart.Data("India", 1017)); data.add(new PieChart.Data("Brazil", 172)); data.add(new PieChart.Data("UK", 59)); data.add(new PieChart.Data("USA", 285)); return data; }
The PieChart
class contains several properties:
- data
- startAngle
- clockwise
- labelsVisible
- labelLineLength
The data
property specifies the content for the chart in an ObservableList<PieChart.Data>
.
The startAngle
property specifies the angle an degrees to start the first pie slice. By default, it is zero degrees, which corresponds to three o’clock position. A positive startAngle is measured anticlockwise.
The clockwise
property specifies whether the slices are placed clockwise starting at the startAngle. By default, it is true.
The labelsVisible
property specifies whether the labels for slices are visible. Labels for slices are displayed close to the slice and they are placed outside the slices. The label for a slice is specified using the name property of the PieChart.Data
class.
In our example, “China”, “India”, “Brazil”, etc., are labels for slices. Labels and slices are connected through straight lines. The labelLineLength property specifies the length of those lines. Its default value is 20.0 pixels. The above program uses a pie chart to display the population for five countries in year 2000.
The program creates an empty pie chart and sets its title. The legend is placed on the left side. Later, it sets the data for the chart.
The data is generated in the getChartData()
method, which returns an ObservableList<PieChart.Data>
containing the name of the countries as the labels for pie slices and their populations as pie values.
2.2 Styling the PieChart with CSS
All properties, except the data property, defined in the PieChart
class, can be styled using CSS as shown below.
piechart.css
.chart { -fx-clockwise: false; -fx-pie-label-visible: true; -fx-label-line-length: 10; -fx-start-angle: 90; } .chart-pie { -fx-border-color: white; -fx-background-insets: 2; }
Four style classes are added to each pie slice added to a pie chart:
- chart-pie
- data<i>
- default-color<i>
- negative
The <i>
in the style-class name data<i>
is the slice index. The first slice has the class data0, the second data1, the third data2 and so on.
The <j>
in the style-class name default-color<j>
is the color index of the series. In a pie chart, you can think of each slice as a series. The default CSS (Modena.css) defines eight series colors. If your pie slice has more than eight slices, the slice color will be repeated.
The negative
style-class is added only when the data for the slice is negative.
The following style will set a white border with 2px of background insets for all pie slices. It will show a wider gap between two slices as you have set 2px insets.
.chart-pie { -fx-border-color: white; -fx-background-insets: 2; }
2.3 The GUI
The following figure shows a pie chart that displays the population of five countries in the year 2000.
3. The XYChart
An instance of a concrete subclass of the abstract XYChart<X,Y>
class defines a two-axis chart. The generic type parameters X and Y are the data type of values plotted along x-axis and y-axis, respectively.
3.1 Representing Axes in an XYChart
An instance of a concrete subclass of the abstract Axis<T>
class defines an axis in the XYChart
.
The abstract Axis<T> class is the base class for all classes representing axes. The generic parameter T
is the type of the values plotted along the axis. An axis displays ticks and tick labels. The Axis<T>
class contains properties to customize the ticks and tick labels. An axis can have a label, which is specified in the label
property.
The concrete subclasses CategoryAxis and NumberAxis are used for plotting String and Number data values along an axis, respectively. They contain properties specific to the data values.
By default, the range of the data on an axis is automatically determined based on the data. You can turn off this feature by setting the autoRanging property in the Axis<T>
class to false.
The following snippet of code creates an instance of the CategoryAxis
and NumberAxis
and sets their labels.
CategoryAxis xAxis = new CategoryAxis(); xAxis.setLabel("Country"); NumberAxis yAxis = new NumberAxis(); yAxis.setLabel("Population (in millions)");
3.2 Adding Data to an XYChart
Data in an XYChart
represents points in the 2D plane defined by the x-axis and y-axis. A point in a 2D plane is specified using the x and y coordinates, which are values along the x-axis and y-axis, respectively. The data in an XYChart
is specified as an ObservableList
of named series. A series consists of multiple data items, which are points in the 2D plane. How the points are rendered depends on the chart type.
An instance of the nested static XYChart.Data<X,Y>
class represents a data item in a series. The class defines the following properties:
- XValue
- YValue
- extraValue
- node
The XValue
and YValue
are the values for the data item along the x-axis and y-axis, respectively. Their data types need to match the data type of the x-axis and y-axis for the chart.
The extraValue
is an Object, which can be used to store any additional
information for the data item. Its use depends of the chart type. If the chart does not
use this value, you can use it for any other purpose: for example, to store the tooltip
value for the data item.
The node
specifies the node to be rendered for the data item in the chart. By default, the chart will create a suitable node depending on the chart type.
Suppose both axes of an XYChart
plot numeric values. The following snippet of code creates some data items for the chart. The data items are the population of China from 1950 to 2150.
XYChart.Series<Number, Number> seriesChina = new XYChart.Series<Number, Number>(); seriesChina.setName("China"); seriesChina.getData().add(new XYChart.Data<Number, Number>(1950, 555)); seriesChina.getData().add(new XYChart.Data<Number, Number>(2000, 1275)); seriesChina.getData().add(new XYChart.Data<Number, Number>(2050, 1395)); seriesChina.getData().add(new XYChart.Data<Number, Number>(2100, 1182)); seriesChina.getData().add(new XYChart.Data<Number, Number>(2150, 1149));
An instance of the nested static XYChart.Series<X,Y> class represents a series of data items. The class defines the following properties:
- name
- data
- chart
- node
The name
is the name of the series.
The data
is an ObservableList of XYChart.Data
. It represents the data for the chart.
The chart
is a read-only reference to the chart to which the series belong.
The node
is a Node
to display for this series. A default node is automatically created based on the chart type.
The following snippet of code creates and adds the data for an XYChart
chart assuming the data series seriesIndia
and seriesUSA
exists.
ObservableList<XYChart.Series<Number, Number>> data = FXCollections.<XYChart.Series<Number, Number>>observableArrayList(); data.add(seriesChina); data.add(seriesIndia); data.add(seriesUSA);
4. The BarChart
4.1 The Code
FxChartsExample2.java
import javafx.application.Application; import javafx.collections.ObservableList; import javafx.scene.Scene; import javafx.scene.chart.BarChart; import javafx.scene.chart.CategoryAxis; import javafx.scene.chart.NumberAxis; import javafx.scene.chart.XYChart; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class FxChartsExample2 extends Application { public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage stage) { // Create the Axis CategoryAxis xAxis = new CategoryAxis(); xAxis.setLabel("Country"); NumberAxis yAxis = new NumberAxis(); yAxis.setLabel("Population (in millions)"); // Create the BarChart BarChart<String, Number> chart = new BarChart<>(xAxis, yAxis); // Set the Title for the Chart chart.setTitle("Population by Country and Year"); // Set the Data for the Chart ObservableList<XYChart.Series<String,Number>> chartData = FxChartUtil.getYearSeries(); chart.setData(chartData); // Create the Stackpane StackPane root = new StackPane(chart); // Set the Style-properties of the Pane root.setStyle("-fx-padding: 10;" + "-fx-border-style: solid inside;" + "-fx-border-width: 2;" + "-fx-border-insets: 5;" + "-fx-border-radius: 5;" + "-fx-border-color: blue;"); // Create the Scene Scene scene = new Scene(root); // Add the Stylesheet to the Scene scene.getStylesheets().add(getClass().getResource("barchart.css").toExternalForm()); // Add the Scene to the Stage stage.setScene(scene); // Set the Title of the Stage stage.setTitle("A Vertical Bar Chart Example"); // Display the Stage stage.show(); } }
A bar chart renders the data items as horizontal or vertical rectangular bars. The lengths of the bars are proportional to the value of the data items.
An instance of the BarChart
class represents a bar chart. In a bar chart, one axis must be a CategoryAxis
and the other a ValueAxis/NumberAxis. The bars are drawn vertically or horizontally, depending on whether the CategoryAxis
is the x-axis or the y-axis.
The BarChart
contain two properties to control the distance between two bars in a category and the distance between two categories:
- barGap
- categoryGap
The default value is 4 pixels for the barGap
and 10 pixels for the categoryGap
.
The BarChart
class contains three constructors to create bar charts by specifying axes, data, and gap between two categories.
- BarChart(Axis<X> xAxis, Axis<Y> yAxis)
- BarChart(Axis<X> xAxis, Axis<Y> yAxis, ObservableList<XYChart.Series<X,Y>> data)
- BarChart(Axis<X> xAxis, Axis<Y> yAxis, ObservableList<XYChart.Series<X,Y>> data, double categoryGap)
Notice that you must specify at least the axes when you create a bar chart. The following snippet of code creates two axes and a bar chart with those axes.
// Create the Axis CategoryAxis xAxis = new CategoryAxis(); xAxis.setLabel("Country"); NumberAxis yAxis = new NumberAxis(); yAxis.setLabel("Population (in millions)"); // Create the BarChart BarChart chart = new BarChart(xAxis, yAxis); // Set the Title for the Chart chart.setTitle("Population by Country and Year");
The bars in the chart will appear vertically as the category axis is added as the x-axis. You can populate the chart with data using its setData()
method.
// Set the Data for the Chart ObservableList<XYChart.Series> chartData = FxChartUtil.getYearSeries(); chart.setData(chartData);
4.2 Styling the BarChart with CSS
By default, a BarChart
is given style-class names: chart
and bar-chart
. The following style sets the default values for the barGap
and categoryGap
properties for all bar charts to 0px and 20px. The bars in the same category will be placed next to each other.
barchart.css
.bar-chart { -fx-bar-gap: 0; -fx-category-gap: 20; }
You can customize the appearance of the bars for each series or each data item in a series. Each data item in a BarChart
is represented by a Node
. The Node
gets four default style-class names:
- chart-bar
- series<i>
- data<j>
- default-color<k>
- negative
In series<i>
, <i>
is the series index. For example, the first series is given the style-class name as series0, the second as series1, etc.
In data<j>
, <j>
is the index of the data item within a series. For example, the first data item in each series gets a style-class name as data0, the second as data1, etc.
In default-color<k>
, <k>
is the series color index. For example, each data item in the first series will get a style-class name as default-color0
, in the second series default-color1
, etc. The default CS defines only eight series colors. The value for <k>
is equal to (i%8), where i is the series index. That is, series colors will repeat if you have more than eight series in a bar chart.
The negative
class is added if the data value is negative.
Each legend item in a bar chart is given the following style-class names:
- chart-bar
- series<i>
- bar-legend-symbol
- default-color<j>
In series<i>
, <i>
is the series index.
In default-color<j>
, <j>
is the color index of the series. The legend color will repeat, as the bar colors do, if the number of series exceeds 8.
4.3 The GUI
The following image shows an example of a vertical bar chart.
5. The StackedBarChart
5.1 The Code
FxChartsExample3.java
import javafx.application.Application; import javafx.collections.ObservableList; import javafx.scene.Scene; import javafx.scene.chart.CategoryAxis; import javafx.scene.chart.NumberAxis; import javafx.scene.chart.StackedBarChart; import javafx.scene.chart.XYChart; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class FxChartsExample3 extends Application { public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage stage) { // Create the X-Axis CategoryAxis xAxis = new CategoryAxis(); // Set the Label for the Axis xAxis.setLabel("Country"); // Add the Categories to the Axis xAxis.getCategories().addAll("China", "India", "Brazil", "UK", "USA"); // Create the Y-Axis NumberAxis yAxis = new NumberAxis(); // Set the Label for the Axis yAxis.setLabel("Population (in millions)"); // Create the Chart StackedBarChart<String, Number> chart = new StackedBarChart<>(xAxis, yAxis); // Set the Title for the Chart chart.setTitle("Population by Country and Year"); // Set the data for the chart ObservableList<XYChart.Series<String, Number>> chartData = FxChartUtil.getYearSeries(); chart.setData(chartData); // Create the Stackpane StackPane root = new StackPane(chart); // Set the Style-properties of the Pane root.setStyle("-fx-padding: 10;" + "-fx-border-style: solid inside;" + "-fx-border-width: 2;" + "-fx-border-insets: 5;" + "-fx-border-radius: 5;" + "-fx-border-color: blue;"); // Create the Scene Scene scene = new Scene(root); // Add the Stylesheet to the Scene scene.getStylesheets().add(getClass().getResource("stackbarchart.css").toExternalForm()); // Add the Scene to the Stage stage.setScene(scene); // Set the Title of the Stage stage.setTitle("A Vertical Stacked Bar Chart Example"); // Display the Stage stage.show(); } }
A stacked bar chart is a variation of the bar chart. In a stacked bar chart, the bars in a category are stacked. Except for the placement of the bars, it works the same way as the bar chart.
An instance of the StackedBarChart class represents a stacked bar chart. The bars can be placed horizontally or vertically. If the x-axis is a CategoryAxis
, the bars are placed vertically. Otherwise, they are placed horizontally. Like the BarChart
, one of the axes must be a CategoryAxis
and the other a ValueAxis/NumberAxis.
The StackedBarChart
class contains a categoryGap
property that defines the gap between bars in adjacent categories. The default gap is 10px. Unlike the BarChart
class, the StackedBarChart
class does not contain a barGap
property, as the bars in one category are always stacked.
The constructors of the StackedBarChart
class are similar to the ones for the BarChart
class. They let you specify the axes, chart data, and category gap.
There is one notable difference in a creating the CategoryAxis
for the BarChart
and the StackedBarChart
. The BarChart
reads the categories values from the data whereas you must explicitly add all category values to the CategoryAxis
for a StackedBarChart
.
// Create the X-Axis CategoryAxis xAxis = new CategoryAxis(); // Set the Label for the Axis xAxis.setLabel("Country"); // Add the Categories to the Axis xAxis.getCategories().addAll("China", "India", "Brazil", "UK", "USA"); // Create the Y-Axis NumberAxis yAxis = new NumberAxis(); // Set the Label for the Axis yAxis.setLabel("Population (in millions)"); // Create the Chart StackedBarChart<String, Number> chart = new StackedBarChart<>(xAxis, yAxis); // Set the Title for the Chart chart.setTitle("Population by Country and Year"); // Set the data for the chart ObservableList<XYChart.Series<String, Number>> chartData = FxChartUtil.getYearSeries(); chart.setData(chartData);
5.2 Styling the StackedBarChart with CSS
By default, a StackedBarChart
is given style-class names: chart
and stacked-bar-chart
.
The following style sets the default value for the categoryGap
properties for all stacked bar charts to 20px. The bars in a category will be placed next to each other.
.stacked-bar-chart { -fx-category-gap: 20; }
5.3 The GUI
The following GUI shows a vertical stacked bar chart.
6. The ScatterChart
6.1 The Code
FxChartsExample4.java
import javafx.application.Application; import javafx.collections.ObservableList; import javafx.scene.Scene; import javafx.scene.chart.NumberAxis; import javafx.scene.chart.ScatterChart; import javafx.scene.chart.XYChart; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class FxChartsExample4 extends Application { public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage stage) { // Create the X-Axis NumberAxis xAxis = new NumberAxis(); xAxis.setLabel("Year"); // Customize the X-Axis, so points are scattered uniformly xAxis.setAutoRanging(false); xAxis.setLowerBound(1900); xAxis.setUpperBound(2300); xAxis.setTickUnit(50); // Create the Y-Axis NumberAxis yAxis = new NumberAxis(); yAxis.setLabel("Population (in millions)"); // Create the ScatterChart ScatterChart<Number,Number> chart = new ScatterChart<>(xAxis, yAxis); // Set the Title for the Chart chart.setTitle("Population by Year and Country"); // Set the Data for the Chart ObservableList<XYChart.Series<Number,Number>> chartData = FxChartUtil.getCountrySeries(); chart.setData(chartData); // Create the Stackpane StackPane root = new StackPane(chart); // Set the Style-properties of the Pane root.setStyle("-fx-padding: 10;" + "-fx-border-style: solid inside;" + "-fx-border-width: 2;" + "-fx-border-insets: 5;" + "-fx-border-radius: 5;" + "-fx-border-color: blue;"); // Create the Scene Scene scene = new Scene(root); // Add the Stylesheet to the Scene scene.getStylesheets().add(getClass().getResource("scatterchart.css").toExternalForm()); // Add the Scene to the Stage stage.setScene(scene); // Set the Title of the Stage stage.setTitle("A Scatter Chart Example"); // Display the Stage stage.show(); } }
A bar chart renders the data items as symbols. All data items in a series use the same symbol. The location of the symbol for a data item is determined by the values on the data item along the x-axis and y-axis.
An instance of the ScatterChart class represents a scatter chart. You can use any type of Axis for the x-axis and y-axis. The class does not define any additional properties. It contains constructors that allow you to a create scatter chart by specifying axes and data.
- ScatterChart(Axis<X> xAxis, Axis<Y> yAxis)
- ScatterChart(Axis<X> xAxis, Axis<Y> yAxis, ObservableList<XYChart.Series<X,Y>> data)
Recall that the autoRanging
for an Axis is set to true by default. If you are using numeric values in a scatter chart, make sure to set the autoRanging
to false. It is important to set the range of the numeric values appropriately to get uniformly distributed points in the chart. Otherwise, the points may be located densely in a small area and it will be hard to read the chart.
The following code snippet shows how to create and populate a scatter chart.
// Create the X-Axis NumberAxis xAxis = new NumberAxis(); xAxis.setLabel("Year"); // Customize the X-Axis, so points are scattered uniformly xAxis.setAutoRanging(false); xAxis.setLowerBound(1900); xAxis.setUpperBound(2300); xAxis.setTickUnit(50); // Create the Y-Axis NumberAxis yAxis = new NumberAxis(); yAxis.setLabel("Population (in millions)"); // Create the ScatterChart ScatterChart<Number,Number> chart = new ScatterChart<>(xAxis, yAxis); // Set the Title for the Chart chart.setTitle("Population by Year and Country"); // Set the Data for the Chart ObservableList<XYChart.Series<Number,Number>> chartData = FxChartUtil.getCountrySeries(); chart.setData(chartData);
Both axes are numeric axes. The x-axis is customized. The autoRanging
is set to false; reasonable lower and upper bounds are set. The tick unit is set to 50. If you do not customize these properties, the ScatterChart
will automatically determine them and the chart data will be hard to read.
6.2 Styling the ScatterChart with CSS
The ScatterChart
is not assigned any additional style-class name other than chart. You can customize the appearance of the symbols for each series or each data item in a series. Each data item in a ScatterChart
is represented by a Node
. The Node
gets four default style-class names:
- chart-symbol
- series<i>
- data<j>
- default-color<k>
- negative
Please refer to the section Styling the BarChart
with CSS for more details on the meanings of <i>
, <j>
, and <k>
in these style-class names. Each legend item in a scatter chart is given the following style-class names:
- chart-symbol
- series<i>
- data<j>
- default-color<k>
The following style will display the data items in the first series as triangles filled in blue. Note that only eight color series are defined. After that, colors are repeated as discussed at length in the section on the pie chart.
scatterchart.css
.chart-symbol.default-color0 { -fx-background-color: blue; -fx-shape: "M5, 0L10, 5L0, 5z"; }
6.3 The GUI
This figure shows an example of a scatter chart. Both axes are numeric axes.
7. The LineChart
7.1 The Code
FxChartsExample5.java
import javafx.application.Application; import javafx.collections.ObservableList; import javafx.scene.Scene; 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 FxChartsExample5 extends Application { public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage stage) { // Create the X-Axis NumberAxis xAxis = new NumberAxis(); xAxis.setLabel("Year"); // Customize the X-Axis, so points are scattered uniformly xAxis.setAutoRanging(false); xAxis.setLowerBound(1900); xAxis.setUpperBound(2200); xAxis.setTickUnit(50); // Create the Y-Axis NumberAxis yAxis = new NumberAxis(); yAxis.setLabel("Population (in millions)"); // Create the LineChart LineChart<Number,Number> chart = new LineChart<>(xAxis, yAxis); // Set the Title for the Chart chart.setTitle("Population by Year and Country"); // Set the Data for the Chart ObservableList<XYChart.Series<Number,Number>> chartData = FxChartUtil.getCountrySeries(); chart.setData(chartData); // Create the Stackpane StackPane root = new StackPane(chart); // Set the Style-properties of the Pane root.setStyle("-fx-padding: 10;" + "-fx-border-style: solid inside;" + "-fx-border-width: 2;" + "-fx-border-insets: 5;" + "-fx-border-radius: 5;" + "-fx-border-color: blue;"); // Create the Scene Scene scene = new Scene(root); // Add the Stylesheet to the Scene scene.getStylesheets().add(getClass().getResource("linechart.css").toExternalForm()); // Add the Scene to the Stage stage.setScene(scene); // Set the Title of the Stage stage.setTitle("A Line Chart Example"); // Display the Stage stage.show(); } }
A line chart displays the data items in a series by connecting them by line segments. Optionally, the data points themselves may be represented by symbols. You can think of a line chart as a scatter chart with symbols in a series connected by straight line segments. Typically, a line chart is used to view the trend in data change over time or in a category.
An instance of the LineChart
class represents a line chart. The class contains a createSymbols
property, which is set to true by default. It controls whether symbols are created for the data points. Set it to false to show only straight lines connecting the data points in a series.
The LineChart
class contains two constructors to create line charts by specifying axes and data.
- LineChart(Axis<X> xAxis, Axis<Y> yAxis)
- LineChart(Axis<X> xAxis, Axis<Y> yAxis, ObservableList<XYChart.Series<X,Y>> data)
The following code snippet shows how to create and populate a line chart.
// Create the X-Axis NumberAxis xAxis = new NumberAxis(); xAxis.setLabel("Year"); // Customize the X-Axis, so points are scattered uniformly xAxis.setAutoRanging(false); xAxis.setLowerBound(1900); xAxis.setUpperBound(2200); xAxis.setTickUnit(50); // Create the Y-Axis NumberAxis yAxis = new NumberAxis(); yAxis.setLabel("Population (in millions)"); // Create the LineChart LineChart<Number,Number> chart = new LineChart<>(xAxis, yAxis); // Set the Title for the Chart chart.setTitle("Population by Year and Country"); // Set the Data for the Chart ObservableList<XYChart.Series<Number,Number>> chartData = FxChartUtil.getCountrySeries(); chart.setData(chartData);
7.2 Styling the LineChart with CSS
The LineChart
is not assigned any additional style-class name other than chart. The following style specifies that the LineChart
should not create symbols.
linechart.css
.chart { -fx-create-symbols: false; }
The LineChart
creates a Path node to show the lines connecting all data points for a series. A line for a series is assigned the following style-class names:
- chart-series-line
- series<i>
- default-color<j>
Here, <i>
is the series index and <j>
is the color index of the series. If the createSymbols
property is set to true, a symbol is created for each data point. Each symbol node is assigned the following style-class name:
- chart-line-symbol
- series<i>
- data<j>
- default-color<k>
Here, <i>
is the series index, <j>
is the data item index within a series, and <k>
is the color index of the series. Each series is assigned a legend item, which gets the following style-class names:
- chart-line-symbol
- series<i>
- default-color<j>
7.3 The GUI
The following image shows the result of the above program, which creates and populates a line chart.
8. The BubbleChart
8.1 The Code
FxChartsExample6.java
import javafx.application.Application; import javafx.collections.ObservableList; import javafx.scene.Scene; import javafx.scene.chart.BubbleChart; import javafx.scene.chart.NumberAxis; import javafx.scene.chart.XYChart; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class FxChartsExample6 extends Application { public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage stage) { // Create the X-Axis NumberAxis xAxis = new NumberAxis(); xAxis.setLabel("Year"); // Customize the X-Axis, so points are scattered uniformly xAxis.setAutoRanging(false); xAxis.setLowerBound(1900); xAxis.setUpperBound(2300); xAxis.setTickUnit(50); // Create the Y-Axis NumberAxis yAxis = new NumberAxis(); yAxis.setLabel("Population (in millions)"); // Create the BubbleCHart BubbleChart<Number,Number> chart = new BubbleChart<>(xAxis, yAxis); // Set the Title for the Chart chart.setTitle("Population by Year and Country"); // Set the Data for the Chart ObservableList<XYChart.Series<Number,Number>> chartData = FxChartUtil.getCountrySeries(); // Set the Bubble Radius setBubbleRadius(chartData); // Set the Data for the Chart chart.setData(chartData); // Create the StackPane StackPane root = new StackPane(chart); // Set the Style-properties of the Pane root.setStyle("-fx-padding: 10;" + "-fx-border-style: solid inside;" + "-fx-border-width: 2;" + "-fx-border-insets: 5;" + "-fx-border-radius: 5;" + "-fx-border-color: blue;"); // Create the Scene Scene scene = new Scene(root); // Add the Stylesheet to the Scene scene.getStylesheets().add(getClass().getResource("bubblechart.css").toExternalForm()); // Add the Scene to the Stage stage.setScene(scene); // Set the Title of the Stage stage.setTitle("A Bubble Chart Example"); // Display the Stage stage.show(); } // Calculate the Bubble Radius private void setBubbleRadius(ObservableList<XYChart.Series<Number,Number>> chartData) { for(XYChart.Series<Number,Number> series: chartData) { for(XYChart.Data<Number,Number> data : series.getData()) { data.setExtraValue(20); // set Bubble radius } } } }
A bubble chart is very similar to a scatter chart, except that it has the ability to represent three values for a data point. A bubble is used to represent a data items in series. You can set the radius of the bubble to represent the third value for the data point.
An instance of the BubbleChart class represents a bubble chart. The class does not define any new properties. A bubble chart uses the extraValue property of the XYChart.Data
class to get the radius of the bubble. The bubble is an ellipse whose radii are scaled based on the scale used for the axes. Bubbles look more like a circle if the scales for x-axis and y-axis are almost equal.
The BubbleChart
class defines two constructors:
- BubbleChart(Axis<X> xAxis, Axis<Y> yAxis)
- BubbleChart(Axis<X> xAxis, Axis<Y> yAxis, ObservableList<XYChart.Series<X,Y>> data)
The following code snippet shows how to create and populate a bubble chart.
// Create the X-Axis NumberAxis xAxis = new NumberAxis(); xAxis.setLabel("Year"); // Customize the X-Axis, so points are scattered uniformly xAxis.setAutoRanging(false); xAxis.setLowerBound(1900); xAxis.setUpperBound(2300); xAxis.setTickUnit(50); // Create the Y-Axis NumberAxis yAxis = new NumberAxis(); yAxis.setLabel("Population (in millions)"); // Create the BubbleCHart BubbleChart<Number,Number> chart = new BubbleChart<>(xAxis, yAxis); // Set the Title for the Chart chart.setTitle("Population by Year and Country"); // Set the Data for the Chart ObservableList<XYChart.Series<Number,Number>> chartData = FxChartUtil.getCountrySeries(); // Set the Bubble Radius setBubbleRadius(chartData); // Set the Data for the Chart chart.setData(chartData);
8.2 Styling the BubbleChart with CSS
The BubbleChart
is not assigned any additional style-class name other than chart
. You can customize the appearance of the bubbles for each series or each data item in a series. Each data item in a BubbleChart
is represented by a Node
. The Node
gets four default style-class names:
- chart-bubble
- series<i>
- data<j>
- default-color<k>
Here, <i>
is the series index, <j>
is the data item index within a series, and <k>
is the color index of the series. Each series is assigned a legend item, which gets the following style-class names:
- chart-bubble
- series<i>
- bubble-legend-symbol
- default-color<k>
Here, <i>
and <k>
have the same meanings as described above. The following style sets the fill color for the series color index 0 to blue. The bubbles and legend symbols for the data items in the first series will be displayed in blue. The color will repeat for series index 8, 16, 24, etc.
bubblechart.css
.chart-bubble.default-color0 { -fx-bubble-fill: blue; }
8.3 The GUI
The following GUI shows a bubble chart.
9. The AreaChart
9.1 The Code
FxChartsExample7.java
import javafx.application.Application; import javafx.collections.ObservableList; import javafx.scene.Scene; import javafx.scene.chart.AreaChart; import javafx.scene.chart.NumberAxis; import javafx.scene.chart.XYChart; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class FxChartsExample7 extends Application { public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage stage) { // Create the X-Axis NumberAxis xAxis = new NumberAxis(); xAxis.setLabel("Year"); // Customize the X-Axis, so points are scattered uniformly xAxis.setAutoRanging(false); xAxis.setLowerBound(1900); xAxis.setUpperBound(2200); xAxis.setTickUnit(50); // Create the Y-Axis NumberAxis yAxis = new NumberAxis(); yAxis.setLabel("Population (in millions)"); // Create the AreaChart AreaChart<Number,Number> chart = new AreaChart<>(xAxis, yAxis); // Set the Title for the Chart chart.setTitle("Population by Year and Country"); // Set the Data for the Chart ObservableList<XYChart.Series<Number,Number>> chartData = FxChartUtil.getCountrySeries(); chart.setData(chartData); // Create the StackPane StackPane root = new StackPane(chart); // Set the Style-properties of the Pane root.setStyle("-fx-padding: 10;" + "-fx-border-style: solid inside;" + "-fx-border-width: 2;" + "-fx-border-insets: 5;" + "-fx-border-radius: 5;" + "-fx-border-color: blue;"); // Create the Scene Scene scene = new Scene(root); // Add the Stylesheet to the Scene scene.getStylesheets().add(getClass().getResource("areachart.css").toExternalForm()); // Add the Scene to the Stage stage.setScene(scene); // Set the Title of the Stage stage.setTitle("An Area Chart Example"); // Display the Stage stage.show(); } }
The area chart is a variation of the line chart. It draws lines connecting all data items in a series and, additionally, fills the area between where the line and the x-axis is painted. Different colors are used to paint areas for different series.
An instance of the AreaChart represents an area chart. Like the LineChart
class, the class contains a createSymbols
property to control whether symbols are drawn at the data points. By default, it is set to true.
The class contains two constructors:
- AreaChart(Axis<X> xAxis, Axis<Y> yAxis)
- AreaChart(Axis<X> xAxis, Axis<Y> yAxis, ObservableList<XYChart.Series<X,Y>> data)
The following code snippet shows how to create and populate an area chart.
// Create the X-Axis NumberAxis xAxis = new NumberAxis(); xAxis.setLabel("Year"); // Customize the X-Axis, so points are scattered uniformly xAxis.setAutoRanging(false); xAxis.setLowerBound(1900); xAxis.setUpperBound(2200); xAxis.setTickUnit(50); // Create the Y-Axis NumberAxis yAxis = new NumberAxis(); yAxis.setLabel("Population (in millions)"); // Create the AreaChart AreaChart<Number,Number> chart = new AreaChart<>(xAxis, yAxis); // Set the Title for the Chart chart.setTitle("Population by Year and Country"); // Set the Data for the Chart ObservableList<XYChart.Series<Number,Number>> chartData = FxChartUtil.getCountrySeries(); chart.setData(chartData);
9.2 Styling the AreaChart with CSS
The AreaChart
is not assigned any additional style-class name other than chart
. The following style specifies that the AreaChart
should not create symbols for representing the data points.
areachart.css
.chart { -fx-create-symbols: false; }
Each series in an AreaChart
is represented by a Group containing two Path
nodes. One Path
represents the line segment connecting all data points in the series, and another Path
represents the area covered by the series. The Path
node representing the line segment for a series is assigned the following style-class names:
- chart-series-area-line
- series<i>
- default-color<j>
Here, <i>
is the series index and <j>
is the color index of the series.
The Path
node representing the area for a series is assigned the following style-class names:
- chart-series-area-fill
- series<i>
- default-color<j>
Here, <i>
is the series index and <j>
is the color index of the series. If the createSymbols
property is set to true, a symbol is created for each data point. Each symbol node is assigned the following style-class name:
- chart-area-symbol
- series<i>
- data<j>
- default-color<k>
Here, <i>
is the series index, <j>
is the data item index within a series, and <k>
is the color index of the series. Each series is assigned a legend item, which gets the following style-class names:
- chart-area-symbol
- series<i>
- area-legend-symbol
- default-color<j>
Here, <i>
is the series index and <j>
is the color index of the series.
9.3 The GUI
The following image shows an area chart.
10. The StackedAreaChart
10.1 The Code
FxChartsExample8.java
import javafx.application.Application; import javafx.collections.ObservableList; import javafx.scene.Scene; import javafx.scene.chart.StackedAreaChart; import javafx.scene.chart.NumberAxis; import javafx.scene.chart.XYChart; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class FxChartsExample8 extends Application { public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage stage) { // Create the X-Axis NumberAxis xAxis = new NumberAxis(); xAxis.setLabel("Year"); // Customize the X-Axis, so points are scattered uniformly xAxis.setAutoRanging(false); xAxis.setLowerBound(1900); xAxis.setUpperBound(2200); xAxis.setTickUnit(50); // Create the Y-Axis NumberAxis yAxis = new NumberAxis(); yAxis.setLabel("Population (in millions)"); // Create the StackedAreaChart StackedAreaChart<Number,Number> chart = new StackedAreaChart<>(xAxis, yAxis); // Set the Title for the Chart chart.setTitle("Population by Year and Country"); // Set the Data for the Chart ObservableList<XYChart.Series<Number,Number>> chartData = FxChartUtil.getCountrySeries(); chart.setData(chartData); // Create the StackPane StackPane root = new StackPane(chart); // Set the Style-properties of the Pane root.setStyle("-fx-padding: 10;" + "-fx-border-style: solid inside;" + "-fx-border-width: 2;" + "-fx-border-insets: 5;" + "-fx-border-radius: 5;" + "-fx-border-color: blue;"); // Create the Scene Scene scene = new Scene(root); // Add the Stylesheet to the Scene scene.getStylesheets().add(getClass().getResource("stackareachart.css").toExternalForm()); // Add the Scene to the Stage stage.setScene(scene); // Set the Title of the Stage stage.setTitle("A Stacked Area Chart Example"); // Display the Stage stage.show(); } }
The stacked area chart is a variation of the area chart. It plots data items by painting an area for each series. Unlike the area chart, areas for series do not overlap; they are stacked.
An instance of the StackedAreaChart represents a stacked area chart. Like the AreaChart
class, the class contains a createSymbols
property.
The class contains two constructors:
- StackedAreaChart(Axis<X> xAxis, Axis<Y> yAxis)
- StackedAreaChart(Axis<X> xAxis, Axis<Y> yAxis, ObservableList<XYChart.Series<X,Y>> data)
The following code snippet shows how to create and populate a stacked area chart.
// Create the X-Axis NumberAxis xAxis = new NumberAxis(); xAxis.setLabel("Year"); // Customize the X-Axis, so points are scattered uniformly xAxis.setAutoRanging(false); xAxis.setLowerBound(1900); xAxis.setUpperBound(2200); xAxis.setTickUnit(50); // Create the Y-Axis NumberAxis yAxis = new NumberAxis(); yAxis.setLabel("Population (in millions)"); // Create the StackedAreaChart StackedAreaChart<Number,Number> chart = new StackedAreaChart<>(xAxis, yAxis); // Set the Title for the Chart chart.setTitle("Population by Year and Country"); // Set the Data for the Chart ObservableList<XYChart.Series<Number,Number>> chartData = FxChartUtil.getCountrySeries(); chart.setData(chartData);
10.2 Styling the StackedAreaChart with CSS
stackareachart.css
Styling a StackedAreaChart
is the same as styling an AreaChart
.
.chart { -fx-create-symbols: false; }
10.3 The GUI
The following GUI shows an example of a stacked area chart.
11. Download Java Source Code
This was an example of javafx.scene.chart
You can download the full source code of this example here: JavaFxChartsExample.zip
thank you✌