【问题标题】:Adding new values in AChartEngine charts在 AChartEngine 图表中添加新值
【发布时间】:2014-10-13 03:14:22
【问题描述】:

有没有办法将数据动态添加到图表中的原始系列(现在,我正在尝试在平移时向折线图添加新数据,但问题更广泛)?添加 new 系列可以正常工作,我可以创建一个新的XYSeries,甚至可以重复使用XYSeriesRenderer 来获得相同的显示。添加到图表时,它会显示,但显然,作为一个新系列,这意味着它不会与以前的数据无缝连接,并且线条上方的显示值将被复制。

如果我保留数据集、系列渲染器和系列本身并尝试在以后重新使用它们,当我尝试series.add(x, y) 我的新值时,我会得到一个看似无限的循环,程序永远不会返回。我还尝试dataset.removeSeries(series),然后再添加新值和dataset.addSeries(series),但徒劳无功。

更新代码:

图表是这样设置的:

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

在 PanListener.panApplied 中调用:

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

【问题讨论】:

  • 请发布一些代码并提及您正在使用的 ACE 版本。
  • 版本为 1.1.0。我会尝试在问题中编辑一些代码,但这并不容易,因为它已经完全融入应用程序...... :-)
  • 基本上,据我所知,与有效版本(以及您的源代码中的示例版本,图表构建器版本)的唯一区别是:在panApplied() 中,我没有创建new XYSeries,而是向其中添加新值并将这个新系列添加到图表中,而是尝试重新使用原始series 对象。
  • 为什么要删除系列并重新添加?只需修改当前系列的内容即可。
  • 这是一种让它发挥作用的尝试。不管有没有,我都会接到同样的不回电话。一旦我从panApplied() 调用series.add(),第一个调用就永远不会返回,我可以在 LogCat 中看到无穷无尽的分配。

标签: android achartengine


【解决方案1】:

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

我还在 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 值来避免这个问题。

【讨论】:

  • 我还在 ACE bugtracker 中提交了issue。解决方案是简单地使用x += Math.ulp(x) 而不是x += getPadding()
  • 我签入了针对此问题的修复程序。
【解决方案2】:

解决问题:有问题的图表是XYChart。当我向右平移并使用 XYSeries.add() 将新项目添加到系列中时,这些新项目位于 before 已经存在的值之前,虽然更新图表线本身显示正常,但图表值显示在各个图表点上方不再与新值保持同步。我就是这样通过修改源码解决的。

源中的问题是 XYChart.drawChartValuesText()receives 一个 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);
}

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-14
    相关资源
    最近更新 更多