-
Notifications
You must be signed in to change notification settings - Fork 32
styling
The goal of this tutorial is to show how the appearance of a plots and its parts can be changed to fit your need. For this purpose, we will create a simple scatter plot and style its plot area, its data points, and its axes.
First, we need some data plot. A simple point cloud with random data will do:
DataTable data = new DataTable(Double.class, Double.class, Double.class);
final int POINT_COUNT = 1000;
java.util.Random rand = new java.util.Random();
for (int i = 0; i < POINT_COUNT; i++) {
double x = rand.nextGaussian();
double y1 = rand.nextGaussian() + x;
double y2 = rand.nextGaussian() - x;
data.add(x, y1, y2);
}
Next, we need to create a new scatter plot which displays the data as two separate data series:
DataSeries series1 = new DataSeries("Series 1", data, 0, 1);
DataSeries series2 = new DataSeries("Series 2", data, 0, 2);
XYPlot plot = new XYPlot(series1, series2);
This is how our unstyled plot looks like:
In order to get enough space for axis labels to be displayed on the left and on the bottom we will add some space to the plot:
double insetsTop = 20.0,
insetsLeft = 60.0,
insetsBottom = 60.0,
insetsRight = 40.0;
plot.setInsets(new Insets2D.Double(
insetsTop, insetsLeft, insetsBottom, insetsRight));
Our plot still lacks a title which describes the plot's contents. So we simply add one by changing the text of the title:
plot.getTitle().setText("Nice scatter");
This is the result of styling the plot:
The plot area is the largest area of the plot. It displays the plot's data points and the user should be able to view it easily. Therefore, we will change the color and width of the border around the plot area:
plot.getPlotArea().setBorderColor(new Color(0.0f, 0.2f, 0.8f));
plot.getPlotArea().setBorderStroke(new BasicStroke(2f));
This is the result of styling the plot area:
To see which point in the scatter plot belongs to which data series it would be nice to change the symbols and colors of all data points belonging to a certain series.
In out case we want all points of Series 1 to be displayed as semi-transparent blue circles.
So we use the following code to change the settings of the corresponding PointRenderer
:
PointRenderer points1 = new DefaultPointRenderer();
points1.setShape(new Ellipse2D.Double(-3.0, -3.0, 6.0, 6.0));
points1.setColor(new Color(0.0f, 0.3f, 1.0f, 0.3f));
plot.setPointRenderers(series1, points1);
We do the same for Series 2 and change it so that all its points are displayed as semi-transparent black rectangles:
PointRenderer points2 = new DefaultPointRenderer();
points2.setShape(new Rectangle2D.Double(-2.5, -2.5, 5.0, 5.0));
points2.setColor(new Color(0.0f, 0.0f, 0.0f, 0.3f));
plot.setPointRenderers(series2, points2);
This is the result of adjusting the point renderers:
Finally, we will make the axes nicer. We'll give each axis a label, so it can be identified:
plot.getAxisRenderers(XYPlot.AXIS_X).get(0).setLabel("X");
plot.getAxisRenderers(XYPlot.AXIS_Y).get(0).setLabel("Y");
Although the default spacing of tick marks usually leads to good results, sometimes
it needs to be adjusted. To get the correct spacing for each axis it is necessary to
chage the TICKS_SPACING
setting of the x and y axis to suitable values:
plot.getAxisRenderers(XYPlot.AXIS_X).get(0).setTickSpacing(1.0);
plot.getAxisRenderers(XYPlot.AXIS_Y).get(0).setTickSpacing(2.0);
Now, we will move the axes to the border of our plot area. To do this, we simply move the intersection point to most negative value that is allowed:
plot.getAxisRenderers(XYPlot.AXIS_X).get(0).setIntersection(-Double.MAX_VALUE);
plot.getAxisRenderers(XYPlot.AXIS_Y).get(0).setIntersection(-Double.MAX_VALUE);
This is the result of styling the axis renderers:
Finally, here is the code for a displaying the plot in a Java Swing frame:
package tutorials.styling;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import javax.swing.JFrame;
import de.erichseifert.gral.data.DataSeries;
import de.erichseifert.gral.data.DataTable;
import de.erichseifert.gral.plots.BarPlot;
import de.erichseifert.gral.plots.PlotArea;
import de.erichseifert.gral.plots.XYPlot;
import de.erichseifert.gral.plots.axes.AxisRenderer;
import de.erichseifert.gral.plots.points.DefaultPointRenderer;
import de.erichseifert.gral.plots.points.PointRenderer;
import de.erichseifert.gral.ui.InteractivePanel;
import de.erichseifert.gral.util.Insets2D;
public class Styling extends JFrame {
public Styling() {
// Create data
DataTable data = new DataTable(Double.class, Double.class, Double.class);
final int POINT_COUNT = 1000;
java.util.Random rand = new java.util.Random();
for (int i = 0; i < POINT_COUNT; i++) {
double x = rand.nextGaussian();
double y1 = rand.nextGaussian() + x;
double y2 = rand.nextGaussian() - x;
data.add(x, y1, y2);
}
// Create series
DataSeries series1 = new DataSeries("Series 1", data, 0, 1);
DataSeries series2 = new DataSeries("Series 2", data, 0, 2);
XYPlot plot = new XYPlot(series1, series2);
// Style the plot
double insetsTop = 20.0,
insetsLeft = 60.0,
insetsBottom = 60.0,
insetsRight = 40.0;
plot.setInsets(new Insets2D.Double(
insetsTop, insetsLeft, insetsBottom, insetsRight));
plot.getTitle().setText("Nice scatter");
// Style the plot area
plot.getPlotArea().setBorderColor(new Color(0.0f, 0.3f, 1.0f));
plot.getPlotArea().setBorderStroke(PlotArea.BORDER, new BasicStroke(2f));
// Style data series
PointRenderer points1 = new DefaultPointRenderer();
points1.setShape(new Ellipse2D.Double(-3.0, -3.0, 6.0, 6.0));
points1.setColor(new Color(0.0f, 0.3f, 1.0f, 0.3f));
plot.setPointRenderers(series1, points1);
PointRenderer points2 = new DefaultPointRenderer();
points2.setShape(new Rectangle2D.Double(-2.5, -2.5, 5, 5));
points2.setColor(new Color(0.0f, 0.0f, 0.0f, 0.3f));
plot.setPointRenderers(series2, points2);
// Style axes
plot.getAxisRenderers(XYPlot.AXIS_X).get(0).setLabel("X");
plot.getAxisRenderers(XYPlot.AXIS_Y).get(0).setLabel("Y");
plot.getAxisRenderers(XYPlot.AXIS_X).get(0).setTickSpacing(1.0);
plot.getAxisRenderers(XYPlot.AXIS_Y).get(0).setTickSpacing(2.0);
plot.getAxisRenderers(XYPlot.AXIS_X).get(0).setIntersection(-Double.MAX_VALUE);
plot.getAxisRenderers(XYPlot.AXIS_Y).get(0).setIntersection(-Double.MAX_VALUE);
// Display on screen
getContentPane().add(new InteractivePanel(plot), BorderLayout.CENTER);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setMinimumSize(getContentPane().getMinimumSize());
setSize(504, 327);
}
public static void main(String[] args) {
Styling df = new Styling();
df.setVisible(true);
}
}