0

Is there a way to dynamically add data to the original series in a chart (right now, I'm trying to add new data to a line chart when panned but the question is broader)? Adding a new series works all right, I can create a new XYSeries and even reuse the XYSeriesRenderer to have the same display. When added to the chart, it will display but, obviously, as a new series, meaning that it won't join seamlessly with the previous data and displayed values above the line will be duplicated.

If I keep the dataset, the series renderer and the series itself and try to re-use them later, I get a seemingly endless loop when I try to series.add(x, y) my new values, the program never returns. I also tried to dataset.removeSeries(series) before adding the new values and dataset.addSeries(series) again but in vain.

Update with code:

The chart is set up like this:

renderer = new XYMultipleSeriesRenderer();
renderer.setAntialiasing(true);
...
renderer.setZoomEnabled(false, false);

dataset = new XYMultipleSeriesDataset();

seriesRenderer = new XYSeriesRenderer();
seriesRenderer.setColor(chartColor);
...
seriesRenderer.setChartValuesTextSize(...);
renderer.addSeriesRenderer(seriesRenderer);

series = new XYSeries("");
...
series.add(x, y);
...
dataset.addSeries(series);

Called in PanListener.panApplied:

dataset.removeSeries(series);
...
series.add(x, y);
...
dataset.addSeries(series);
4

2 回答 2

0

如果您的新系列的起点是旧系列的终点,您可能会遇到和我一样的问题:

我还在 XYSeries.add(x,y) 中遇到了一个无限循环,当添加第二个 x/y 对时,它的 x 值与前一对相同。在我的例子中,x 是 long 类型,代表一个时间戳。死循环的原因在方法的源码中很容易找到:

public synchronized void add(double x, double y) {
  while (mXY.get(x) != null) {
    // add a very small value to x such as data points sharing the same x will
    // still be added
    x += getPadding(); // Defined as constant: PADDING = 0.000000000001
   }
   mXY.put(x, y);
   updateRange(x, y);
 }

如果 x 太大,那么添加非常小的“填充”不会改变 x 的值,while 循环中的条件永远不会改变。(如果增量太小,double 不会真正改变。)

我通过确保不要两次添加相同的 x 值来避免这个问题。

于 2013-09-23T19:58:32.077 回答
0

解决问题:有问题的图表是XYChart. 当我向右平移并使用XYSeries.add()该位于现有值之前的序列向系列添加新项目时,尽管更新图表线本身显示正常,但显示在各个图表点上方的图表值不再与新值保持同步。这就是我通过修改源来解决它的方法。

源代码中的问题是XYChart.drawChartValuesText()接收一个startIndex参数并使用它来查找要显示的标签的值,XYSeries.getY()这就是问题所在。所以,在大XYChart.draw()函数中,在我们真正调用 之前drawSeries(),我设置了一个新变量:

final List<Double> chartValues = new ArrayList<Double>();

除了values稍后的列表之外,我还将实际值添加到此列表中:

values.add(xValue);
values.add(yValue);
chartValues.add(yValue);

并在调用下一个函数时传递它(这在源代码中发生了两次):

drawSeries(series, canvas, paint, points, seriesRenderer, yAxisValue, i, or, startIndex, chartValues);

XYChart.drawSeries(),反过来,将其传递给:

drawChartValuesText(canvas, series, seriesRenderer, paint, pointsList, seriesIndex, startIndex, values);

最后,XYChart.drawChartValuesText()使用这些新值而不是startIndex基于 - 的查找:

protected void drawChartValuesText(Canvas canvas, XYSeries series, XYSeriesRenderer renderer, Paint paint, List<Float> points, int seriesIndex, int startIndex, List<Double> values) {
  if (points.size() > 2) { // there are more than one point
    // record the first point's position
    float previousPointX = points.get(0);
    float previousPointY = points.get(1);
    for (int k = 0; k < points.size(); k += 2)
      if (k == 2) { // decide whether to display first two points' values or not
        if (Math.abs(points.get(2) - points.get(0)) > renderer.getDisplayChartValuesDistance() || Math.abs(points.get(3) - points.get(1)) > renderer.getDisplayChartValuesDistance()) {
          // first point
          drawText(canvas, getLabel(renderer.getChartValuesFormat(), values.get(k)), points.get(0), points.get(1) - renderer.getChartValuesSpacing(), paint, 0);
          // second point
          drawText(canvas, getLabel(renderer.getChartValuesFormat(), values.get(k + 1)), points.get(2), points.get(3) - renderer.getChartValuesSpacing(), paint, 0);

          previousPointX = points.get(2);
          previousPointY = points.get(3);
        }
      }
      else if (k > 2)
        // compare current point's position with the previous point's, if they are not too close, display
        if (Math.abs(points.get(k) - previousPointX) > renderer.getDisplayChartValuesDistance() || Math.abs(points.get(k + 1) - previousPointY) > renderer.getDisplayChartValuesDistance()) {
          drawText(canvas, getLabel(renderer.getChartValuesFormat(), values.get(k / 2)), points.get(k), points.get(k + 1) - renderer.getChartValuesSpacing(), paint, 0);
          previousPointX = points.get(k);
          previousPointY = points.get(k + 1);
        }
  }
  else
    for (int k = 0; k < points.size(); k += 2)
      drawText(canvas, getLabel(renderer.getChartValuesFormat(), values.get(k / 2)), points.get(k), points.get(k + 1) - renderer.getChartValuesSpacing(), paint, 0);
}

这个解决方法现在似乎为我解决了这个问题,但如果我以后发现任何问题,我会报告。

于 2014-10-12T18:53:43.133 回答