Glory to Russia
Glory to Russia

Reputation: 18712

How to fixate the domain range of a JFreeChart XY diagram?

I have a JFreeChart chart, which displays measurements from a sensor. The diagram should show how those values change over time.

I create the diagram using following code:

    // create the chart...
    final JFreeChart chart = ChartFactory.createXYLineChart(
        "Pulse sensor data",      // chart title
        "X",                      // x axis label
        "Y",                      // y axis label
        dataset,                  // data
        PlotOrientation.VERTICAL,
        true,                     // include legend
        true,                     // tooltips
        false                     // urls
    );

    // NOW DO SOME OPTIONAL CUSTOMISATION OF THE CHART...
    chart.setBackgroundPaint(Color.white);


    // get a reference to the plot for further customisation...
    final XYPlot plot = chart.getXYPlot();
    plot.setBackgroundPaint(Color.lightGray);
    plot.setDomainGridlinePaint(Color.white);
    plot.setRangeGridlinePaint(Color.white);

    final XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();

    renderer.setDrawSeriesLineAsPath(true);

    renderer.setSeriesLinesVisible(0, true);
    renderer.setSeriesShapesVisible(0, false);
    plot.setRenderer(renderer);

    // change the auto tick unit selection to integer units only...
    final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
    rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());

There is a problem with this implementation - the domain axis constantly changes, hence, the representation of the signals changes as well. Therefore, it is hard to tell visually whether the signal has changed significantly.

At the start of a measurement session the domain ranges from 0 to approx. 550.

enter image description here

After some time I get more data and now the maximum value is 35000.

enter image description here

If we wait longer, it changes again (actually, with every received measurement a litlle).

enter image description here

How can I change the code such that the diagram shows last X measurements (i. e. the size of the domain axis remains constants) and kind of slides over the time?

Update 1 (01.06.2013 18:06 MSK): I changed the code for adding a new data item to

sensorSeries.add(new Millisecond(new Date()), voltage);

where voltage is the new sensor value.

The code for setting up the chart has also changed:

dataset = new TimeSeriesCollection();

sensorSeries = new TimeSeries("Pulse sensor data");
sensorSeries.setMaximumItemAge(12500);

dataset.addSeries(sensorSeries);

final JFreeChart chart = createChart(dataset);

[...]

private JFreeChart createChart(final XYDataset dataset) {        
    // create the chart...              
    final JFreeChart chart = ChartFactory.createTimeSeriesChart(
        "Pulse sensor data",      // chart title
        "X",                      // x axis label
        "Y",                      // y axis label
        dataset,                  // data
        true,                     // include legend
        true,                     // tooltips
        false                     // urls
    );

    final XYPlot plot = chart.getXYPlot();
    ValueAxis domain = plot.getDomainAxis();
    domain.setAutoRange(true);        

    final ValueAxis rangeAxis = plot.getRangeAxis();
    rangeAxis.setAutoRange(true);

    return chart;
}

This works fine except that I sometimes get following exception:

Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: Index: 1201, Size: 1201
    at java.util.ArrayList.RangeCheck(Unknown Source)
    at java.util.ArrayList.get(Unknown Source)
    at org.jfree.data.time.TimeSeries.getRawDataItem(TimeSeries.java:422)
    at org.jfree.data.time.TimeSeries.getTimePeriod(TimeSeries.java:454)
    at org.jfree.data.time.TimeSeriesCollection.getXValue(TimeSeriesCollection.java:428)
    at org.jfree.chart.renderer.xy.XYLineAndShapeRenderer.drawPrimaryLine(XYLineAndShapeRenderer.java:987)
    at org.jfree.chart.renderer.xy.XYLineAndShapeRenderer.drawItem(XYLineAndShapeRenderer.java:913)
    at org.jfree.chart.plot.XYPlot.render(XYPlot.java:3828)
    at org.jfree.chart.plot.XYPlot.draw(XYPlot.java:3389)
    at org.jfree.chart.JFreeChart.draw(JFreeChart.java:1237)
    at org.jfree.chart.ChartPanel.paintComponent(ChartPanel.java:1672)
    at javax.swing.JComponent.paint(Unknown Source)
    at javax.swing.JComponent.paintToOffscreen(Unknown Source)

Any ideas how to fix it?

Upvotes: 3

Views: 2647

Answers (1)

trashgod
trashgod

Reputation: 205785

How can I execute adding the data in the event dispatch thread?

As shown here, SwingWorker is ideal for this. Poll or listen to your data source in the worker's doInBackground() method and update the chart's model in process(), which executes on the event dispatch thread.

image

Upvotes: 1

Related Questions