I am trying to create a line chart using JfreeChart API. The x axis receives data as long (milliseconds) and Y axis as a double.
As I am using the dynamic template I am passing data to it via Add_Point method from separate thread and chart is constantly updated via this method. Data comes in irregularly without any periodicity which perhaps makes it even trickier.
I cannot find a way to convert long into digestible for Jfreechart format without working example of it. It seems that I have exhausted all options but my guess is that there are a lot of people out there who have already been through this and have a ready answer.
All I want to do is to reflect correct time on X axis labels every minute with data points correctly spaced over respective point in time. By correct time I mean long value passed to method and not current system time.
Here is the code:
import java.awt.BorderLayout;
import javax.swing.JPanel;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.time.FixedMillisecond;
import org.jfree.data.time.Millisecond;
import org.jfree.data.time.RegularTimePeriod;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.ApplicationFrame;
public class DynamicDataDemo extends ApplicationFrame {
/** The time series data. */
private static TimeSeries series;
public DynamicDataDemo(final String title) {
super(title);
this.series = new TimeSeries("Random Data", Millisecond.class);
final TimeSeriesCollection dataset = new TimeSeriesCollection(this.series);
final JFreeChart chart = createChart(dataset);
final ChartPanel chartPanel = new ChartPanel(chart);
final JPanel content = new JPanel(new BorderLayout());
content.add(chartPanel);
chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
setContentPane(content);
}
private JFreeChart createChart(final XYDataset dataset) {
final JFreeChart result = ChartFactory.createTimeSeriesChart(
"Dynamic Data Demo",
"Time",
"Value",
dataset,
true,
true,
false
);
final XYPlot plot = result.getXYPlot();
ValueAxis axis = plot.getDomainAxis();
axis.setAutoRange(true);
axis.setFixedAutoRange(60000.0); // 60 seconds
axis = plot.getRangeAxis();
axis.setRange(9000.0, 11000.0);
return result;
}
public static void Add_Point(long x, double y){
series.add(new Millisecond(), y);
// series.add(new FixedMillisecond(x), y); }
}
If your x values are milliseconds from the Java epoch, you can do it like this:
series.add(new Millisecond(new Date(x)), y);
If not, you'll have to scale and/or offset the value.
Related
On an XYPlot, I want the coordinates of mouse displayed as hint near to mouse, but only when (the mouse) move on chart! In another words, when the crosshair moves to another point, the positioning of the coordinate values would move too, following the crosshair.
Also 1 horizontal line and 1 vertical line will be drawn, that intersects specifically at the point that mouse is over on.
Is this possible?
Until now I can get the coordinates and printed on console using ChartMouseListener and chartMouseMoved method.
This is my project and how I want to be the chart with mouse.
JFreeChart has quite flexible support for crosshairs. To do what you described I would use an Overlay on the ChartPanel, and update the crosshairs from your ChartMouseListener. Here is a self-contained example (which I'll add to the collection of demos that we ship with the JFreeChart Developer Guide):
package org.jfree.chart.demo;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartMouseEvent;
import org.jfree.chart.ChartMouseListener;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.panel.CrosshairOverlay;
import org.jfree.chart.plot.Crosshair;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.general.DatasetUtilities;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.RectangleEdge;
/**
* A demo showing crosshairs that follow the data points on an XYPlot.
*/
public class CrosshairOverlayDemo1 extends JFrame implements ChartMouseListener {
private ChartPanel chartPanel;
private Crosshair xCrosshair;
private Crosshair yCrosshair;
public CrosshairOverlayDemo1(String title) {
super(title);
setContentPane(createContent());
}
private JPanel createContent() {
JFreeChart chart = createChart(createDataset());
this.chartPanel = new ChartPanel(chart);
this.chartPanel.addChartMouseListener(this);
CrosshairOverlay crosshairOverlay = new CrosshairOverlay();
this.xCrosshair = new Crosshair(Double.NaN, Color.GRAY, new BasicStroke(0f));
this.xCrosshair.setLabelVisible(true);
this.yCrosshair = new Crosshair(Double.NaN, Color.GRAY, new BasicStroke(0f));
this.yCrosshair.setLabelVisible(true);
crosshairOverlay.addDomainCrosshair(xCrosshair);
crosshairOverlay.addRangeCrosshair(yCrosshair);
chartPanel.addOverlay(crosshairOverlay);
return chartPanel;
}
private JFreeChart createChart(XYDataset dataset) {
JFreeChart chart = ChartFactory.createXYLineChart("Crosshair Demo",
"X", "Y", dataset);
return chart;
}
private XYDataset createDataset() {
XYSeries series = new XYSeries("S1");
for (int x = 0; x < 10; x++) {
series.add(x, x + Math.random() * 4.0);
}
XYSeriesCollection dataset = new XYSeriesCollection(series);
return dataset;
}
#Override
public void chartMouseClicked(ChartMouseEvent event) {
// ignore
}
#Override
public void chartMouseMoved(ChartMouseEvent event) {
Rectangle2D dataArea = this.chartPanel.getScreenDataArea();
JFreeChart chart = event.getChart();
XYPlot plot = (XYPlot) chart.getPlot();
ValueAxis xAxis = plot.getDomainAxis();
double x = xAxis.java2DToValue(event.getTrigger().getX(), dataArea,
RectangleEdge.BOTTOM);
double y = DatasetUtilities.findYValue(plot.getDataset(), 0, x);
this.xCrosshair.setValue(x);
this.yCrosshair.setValue(y);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
CrosshairOverlayDemo1 app = new CrosshairOverlayDemo1(
"JFreeChart: CrosshairOverlayDemo1.java");
app.pack();
app.setVisible(true);
}
});
}
}
I am using JFreeChart to make a barchart vs time. For some reason on these charts, the tick labels on the x axis turn into "..." occasionally. There seems like there is plenty of room for the labels to expand, but instead it just cuts off the whole thing. How can I fix this.
I tried uploading a picture using the image button, but it does not seem to be working.
Here is code with a similar set up to my project. Strangely it acted different then what is happening to my build. On mine instead of saying "Hou...", it just says "...". Ignore comments and all other uneeded things please.
package dataDisplay;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.sql.SQLException;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.chart.renderer.category.CategoryItemRenderer;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.data.category.DefaultCategoryDataset;
public class mockTest extends JPanel{
ChartPanel chartPanel;
JFreeChart chart;
CategoryAxis domainAxis;
NumberAxis rangeAxis;
public mockTest()
{
//Mock data
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
int[] times = new int[]{1,2,3,4,5,6,7,8,9,10,11,12};
for ( int i = 0; i < times.length; i++ ){
dataset.addValue(times[i], "Time", "Houreee" + String.valueOf(i+1));;
}
CategoryPlot plot = new CategoryPlot();
//create the plot
//add the first dataset, and render as bar values
CategoryItemRenderer renderer = new BarRenderer();
plot.setDataset(0,dataset);
plot.setRenderer(0,renderer);
//set axis
domainAxis = new CategoryAxis("Time");
rangeAxis = new NumberAxis("Value");
plot.setDomainAxis(0,domainAxis);
plot.setRangeAxis(rangeAxis);
chart = new JFreeChart(plot);
chartPanel = new ChartPanel( chart );
this.addComponentListener(new ComponentAdapter() {
#Override
/**
* Makes it so it does not stretch out text. Resizes the fonts to scale with the screen width..
*/
public void componentResized(ComponentEvent e) {
chartPanel.setMaximumDrawHeight(e.getComponent().getHeight());
chartPanel.setMaximumDrawWidth(e.getComponent().getWidth());
chartPanel.setMinimumDrawWidth(e.getComponent().getWidth());
chartPanel.setMinimumDrawHeight(e.getComponent().getHeight());
// Makes the font size scale according to the width of the chart panel.
rangeAxis.setLabelFont(new Font("SansSerif", Font.PLAIN,e.getComponent().getWidth()/60));
domainAxis.setTickLabelFont(new Font("SansSerif", Font.PLAIN,e.getComponent().getWidth()/80));
rangeAxis.setTickLabelFont(new Font("SansSerif", Font.PLAIN,e.getComponent().getWidth()/75));
}
});
this.add(chartPanel, "Center");
}
public static void main (String[] args)
{
// Get the default toolkit
Toolkit toolkit = Toolkit.getDefaultToolkit();
// Get the current screen size
Dimension scrnsize = toolkit.getScreenSize();
int scrnWidth= (int)scrnsize.getWidth();
int scrnHeight = (int) scrnsize.getHeight();
JFrame J= new JFrame();
JPanel jP = new JPanel();
J.setContentPane(jP);
J.setSize(scrnWidth, scrnHeight);
jP.setBackground(Color.white);
jP.setBounds(0,0,scrnWidth,scrnHeight);
int xPercent= 50;
int yPercent = 50;
int widthPercent=50;
int heightPercent=43;
jP.setLayout(null);
jP.setSize(scrnWidth, scrnHeight);
mockTest b= new mockTest();
jP.add(b);
b.setBounds(new Rectangle((int)(scrnWidth*((double)xPercent/100)),(int)(scrnHeight*((double)yPercent/100)),(int)(scrnWidth*((double)widthPercent/100)),(int)(scrnHeight*((double)heightPercent/100))));
J.setUndecorated(true);
J.setVisible(true);
}
Don't use a null layout; let the layout manager do the work. The default layout of JPanel is FlowLayout, which ignores your subsequent changes. In the example below,
The chartPanel is given a GridLayout; when added to the enclosing frame's CENTER, the chart will be free to grow as the frame is resized.
Avoid unnecessarily nested panels.
Use setExtendedState() to maximize the frame.
If necessary, use one of the approaches suggested here to alter the chart's initial size.
If you choose to alter a Font, use deriveFont() to avoid abrupt disparities in the user's chosen settings.
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.JFrame;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.chart.renderer.category.CategoryItemRenderer;
import org.jfree.data.category.DefaultCategoryDataset;
/** #see https://stackoverflow.com/a/31014252/230513 */
public class Test {
public void display() {
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
for (int i = 0; i < 12; i++) {
dataset.addValue(i, "Time", "Hours" + String.valueOf(i + 1));
}
CategoryPlot plot = new CategoryPlot();
CategoryItemRenderer renderer = new BarRenderer();
plot.setDataset(0, dataset);
plot.setRenderer(0, renderer);
CategoryAxis domainAxis = new CategoryAxis("Time");
NumberAxis rangeAxis = new NumberAxis("Value");
plot.setDomainAxis(0, domainAxis);
plot.setRangeAxis(rangeAxis);
JFreeChart chart = new JFreeChart(plot);
ChartPanel chartPanel = new ChartPanel(chart);
chartPanel.setLayout(new GridLayout());
JFrame f = new JFrame();
f.add(chartPanel);
f.setExtendedState(f.getExtendedState() | JFrame.MAXIMIZED_BOTH);
f.setUndecorated(true);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Test()::display);
}
}
I'm a beginner in JFreeChart. I want to change the x axis values of this chart to milliseconds, with 5 ms intervals. I've tried
axis.setTickUnit(new DateTickUnit(DateTickUnitType.MILLISECOND, 5));
but I keep having a compilation error. I found somme suggestions in the net, but nothing worked for me. Also, is there any way to set a maximum value for the x axis, like 300 ms.
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.DateTickUnit;
import org.jfree.chart.axis.DateTickUnitType;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.category.IntervalCategoryDataset;
import org.jfree.data.gantt.GanttCategoryDataset;
import org.jfree.data.gantt.Task;
import org.jfree.data.gantt.TaskSeries;
import org.jfree.data.gantt.TaskSeriesCollection;
import org.jfree.data.time.SimpleTimePeriod;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
public class Gantt extends ApplicationFrame {
private static final long serialVersionUID = 1L;
public Gantt(final String title) {
super(title);
final GanttCategoryDataset dataset = createDataset();
final JFreeChart chart = createChart(dataset);
// add the chart to a panel...
final ChartPanel chartPanel = new ChartPanel(chart);
chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
setContentPane(chartPanel);
}
public static GanttCategoryDataset createDataset() {
final TaskSeries s1 = new TaskSeries("P0");
final Task t4 = new Task("P0", new SimpleTimePeriod(5, 50));
final Task st41 = new Task("1", new SimpleTimePeriod(5, 10));
// st41.setPercentComplete(1.0);
final Task st42 = new Task("2", new SimpleTimePeriod(20, 30));
final Task st43 = new Task("3", new SimpleTimePeriod(40, 50));
t4.addSubtask(st41);
t4.addSubtask(st42);
t4.addSubtask(st43);
s1.add(t4);
final TaskSeries s2 = new TaskSeries("P1");
final Task t2 = new Task("P", new SimpleTimePeriod(0, 10));
final Task st21 = new Task("11", new SimpleTimePeriod(5, 10));
final Task st22 = new Task("21", new SimpleTimePeriod(20, 30));
final Task st23 = new Task("31", new SimpleTimePeriod(35, 90));
t2.addSubtask(st21);
t2.addSubtask(st22);
t2.addSubtask(st23);
s2.add(t2);
final TaskSeriesCollection collection = new TaskSeriesCollection();
collection.add(s1);
collection.add(s2);
return collection;
}
/* private static Date date(final int day, final int month, final int year) {
final Calendar calendar = Calendar.getInstance();
calendar.set(year, month, day);
final Date result = calendar.getTime();
return result;
*/
private JFreeChart createChart(final GanttCategoryDataset dataset) {
final JFreeChart chart = ChartFactory.createGanttChart(
"Gantt ", // chart title
"PRO", // domain axis label
"TIME", // range axis label
dataset, // data
true, // include legend
true, // tooltips
false // urls
);
CategoryPlot plot = chart.getCategoryPlot();
DateAxis axis = (DateAxis) plot.getRangeAxis();
//axis.setTickUnit(new DateTickUnit(DateTickUnitType.MILLISECOND, 10));
axis.setDateFormatOverride(new SimpleDateFormat("S"));
return chart;
}
public static void main(final String[] args) {
final Gantt demo = new Gantt("Gantt");
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
}
}
Some possibilities to consider:
Specify the units in the corresponding axis label when creating the chart.
"TIME (ms)", // range axis label
Use setDateFormatOverride() to change the format of the axis labels, e.g. three-digit values.
DateAxis axis = (DateAxis) plot.getRangeAxis();
axis.setDateFormatOverride(new SimpleDateFormat("SSS"));
Use setMaximumDate(), if warranted.
axis.setMaximumDate(new Date(300));
I am new to jFreeChart. I am trying to run the example code provided with the download. It is working fine. I want to display integer values on the x-axis. I changed the program to use NumberAxis instead of DateAxis. However, when I generated the graph, it displays my integer x values prefixed with "19:00:00." (it should be 5, 10 but it shows 19:00:00.005, 19:00:00.010). What am I doing wrong here?
import java.awt.Color;
import java.text.SimpleDateFormat;
import java.io.File;
import javax.swing.JPanel;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.StandardChartTheme;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.time.Month;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RectangleInsets;
import org.jfree.ui.RefineryUtilities;
import org.jfree.chart.ChartUtilities;
/**
* An example of a time series chart. For the most part, default settings are
* used, except that the renderer is modified to show filled shapes (as well as
* lines) at each data point.
*/
public class PlotExample3 extends ApplicationFrame {
private static final long serialVersionUID = 1L;
{
// set a theme using the new shadow generator feature available in
// 1.0.14 - for backwards compatibility it is not enabled by default
ChartFactory.setChartTheme(new StandardChartTheme("JFree/Shadow",
true));
}
/**
* A demonstration application showing how to create a simple time series
* chart. This example uses monthly data.
*
* #param title the frame title.
*/
public PlotExample3(String title) {
super(title);
ChartPanel chartPanel = (ChartPanel) createDemoPanel();
chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
setContentPane(chartPanel);
}
/**
* Creates a chart.
*
* #param dataset a dataset.
*
* #return A chart.
*/
private static JFreeChart createChart(XYDataset dataset) {
JFreeChart chart = ChartFactory.createTimeSeriesChart(
"Test", // title
"X", // x-axis label
"Y", // y-axis label
dataset, // data
true, // create legend?
true, // generate tooltips?
false // generate URLs?
);
chart.setBackgroundPaint(Color.white);
final XYPlot plot = chart.getXYPlot();
plot.setBackgroundPaint(Color.lightGray);
// plot.setAxisOffset(new Spacer(Spacer.ABSOLUTE, 5.0, 5.0, 5.0, 5.0));
plot.setDomainGridlinePaint(Color.white);
plot.setRangeGridlinePaint(Color.white);
final XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
renderer.setSeriesLinesVisible(1, false);
renderer.setSeriesShapesVisible(1, false);
plot.setRenderer(renderer);
// change the auto tick unit selection to integer units only...
final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
return chart;
}
/**
* Creates a dataset, consisting of two series of monthly data.
*
* #return The dataset.
*/
private static XYDataset createDataset() {
XYSeries s1 = new XYSeries("Test");
s1.add(1, 181.8);
s1.add(2, 167.3);
s1.add(3, 153.8);
s1.add(4, 167.6);
s1.add(5, 158.8);
s1.add(7, 148.3);
s1.add(8, 153.9);
s1.add(9, 142.7);
s1.add(10,123.2);
s1.add(11,131.8);
s1.add(12,139.6);
// ******************************************************************
// More than 150 demo applications are included with the JFreeChart
// Developer Guide...for more information, see:
//
// > http://www.object-refinery.com/jfreechart/guide.html
//
// ******************************************************************
XYSeriesCollection dataset = new XYSeriesCollection();
dataset.addSeries(s1);
return dataset;
}
/**
* Creates a panel for the demo (used by SuperDemo.java).
*
* #return A panel.
*/
public static JPanel createDemoPanel() {
JFreeChart chart = createChart(createDataset());
ChartPanel panel = new ChartPanel(chart);
try {
ChartUtilities.saveChartAsPNG(new File("C:/Users/pb/Pictures/MyChart.png"),chart,1000,1000);
} catch(Exception e) {
System.err.println(e.getMessage());
}
panel.setFillZoomRectangle(true);
panel.setMouseWheelEnabled(true);
return panel;
}
/**
* Starting point for the demonstration application.
*
* #param args ignored.
*/
public static void main(String[] args) {
PlotExample3 demo = new PlotExample3("Time Series Chart Demo 1");
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
}
}
ChartFactory.createTimeSeriesChart() creates a chart with a DateAxis for the x-axis and a NumberAxis for the y-axis. The Javadocs for this method even say that: "A time series chart is an XYPlot with a DateAxis for the x-axis and a NumberAxis for the y-axis."
You should try ChartFactory.createXYLineChart() which will give you a NumberAxis for the x-axis.
I have a JFree XY Line chart which always starts at x = 0. Then based on user defined settings from a properties file, the application increments based on that number (this represents the time in minutes).
For example, x = 0 to start the user defined setting is 5 so the scale goes 0, 5, 10, 15, 20…, or the user setting is 3 so it goes 0, 3, 6, 9, 12… Pretty simple.
The issue I am having is the way in which the graph starts. If I start at 0, then 0 is in the middle of the graph rather than at the bottom left with -0.0000005, -0.000004, -0.000003… 0.000000 , 0.000001 , 0.000002… 0.000005
How can I just manually add the scale at the bottom, i.e. define it should be increments of 2 and then maintain it?
You should use NumberAxis, which contains a lot of methods to define the scale of your chart.
Example :
// Create an XY Line chart
XYSeries series = new XYSeries("Random Data");
series.add(1.0, 500.2);
series.add(10.0, 694.1);
XYSeriesCollection data = new XYSeriesCollection(series);
JFreeChart chart = ChartFactory.createXYLineChart("XY Series Demo", "X", "Y", data,
PlotOrientation.VERTICAL,
true, true, false);
// Create an NumberAxis
NumberAxis xAxis = new NumberAxis();
xAxis.setTickUnit(new NumberTickUnit(2));
// Assign it to the chart
XYPlot plot = (XYPlot) chart.getPlot();
plot.setDomainAxis(xAxis);
Based on this example, here's an sscce that uses setTickUnit() to adjust the domain axis tick unit dynamically, starting from the value 5.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
/** #see https://stackoverflow.com/a/14167983/230513 */
public class SSCCE {
private static final int COUNT = 100;
private static final int UNITS = 5;
private static final Random r = new Random();
public static void main(String[] args) {
XYSeries series = new XYSeries("Data");
for (int i = 0; i < COUNT; i++) {
series.add(i, r.nextGaussian());
}
XYSeriesCollection data = new XYSeriesCollection(series);
final JFreeChart chart = ChartFactory.createXYLineChart("TickUnits",
"X", "Y", data, PlotOrientation.VERTICAL, true, true, false);
XYPlot plot = (XYPlot) chart.getPlot();
final NumberAxis xAxis = (NumberAxis) plot.getDomainAxis();
xAxis.setTickUnit(new NumberTickUnit(UNITS));
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame f = new JFrame("TickUnitDemo");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new ChartPanel(chart));
final JSpinner spinner = new JSpinner(
new SpinnerNumberModel(UNITS, 1, COUNT, 1));
spinner.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
JSpinner s = (JSpinner) e.getSource();
Number n = (Number) s.getValue();
xAxis.setTickUnit(new NumberTickUnit(n.intValue()));
}
});
JPanel p = new JPanel();
p.add(new JLabel(chart.getTitle().getText()));
p.add(spinner);
f.add(p, BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
});
}
}