【问题标题】:How to fixate the domain range of a JFreeChart XY diagram?如何固定 JFreeChart XY 图的域范围?
【发布时间】:2013-06-01 13:16:23
【问题描述】:

我有一个 JFreeChart 图表,它显示来自传感器的测量值。该图应显示这些值如何随时间变化。

我使用以下代码创建图表:

    // 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());

这个实现存在一个问题 - 域轴不断变化,因此信号的表示也会发生变化。因此,很难从视觉上判断信号是否发生了显着变化。

在测量会话开始时,域的范围从 0 到大约。 550.

一段时间后我得到更多数据,现在最大值为 35000。

如果我们等待更长的时间,它会再次发生变化(实际上,每次接收到的测量值都是一点点)。

如何更改代码以使图表显示最后 X 测量值(即域轴的大小保持不变)和随时间推移的幻灯片类型?

更新 1(01.06.2013 18:06 MSK):我将添加新数据项的代码更改为

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

其中voltage 是新的传感器值。

设置图表的代码也发生了变化:

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;
}

这很好用,只是我有时会遇到以下异常:

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)

有什么解决办法吗?

【问题讨论】:

  • @trashgod 谢谢。请参阅我的更新 1。
  • 发生的事情有时总是让我想到不正确的同步;确保您正在更新 event dispatch thread 上的模型(数据集)。
  • @trashgod 我有 2 个线程 - 一个在其中运行 JFrame,另一个在其中侦听传感器并向数据集添加值。如何在事件派发线程中执行添加数据?
  • 我已经在下面详细说明了。

标签: java jfreechart


【解决方案1】:

如何在事件派发线程中执行添加数据?

here 所示,SwingWorker 是理想的选择。在 worker 的 doInBackground() 方法中轮询或侦听您的数据源,并在 process() 中更新图表的模型,该模型在事件调度线程上执行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-24
    • 1970-01-01
    相关资源
    最近更新 更多