2010-03-16 2 views
4

Как вы создадите строку в JasperReports, которая следует за трендом данных, помимо отображения точек данных? Вот до и после выстрела:Строка отчета о трендах

Перед

После

В отчете Time Series не оказывает какого-либо такой вариант, чтобы нарисовать оранжевую линию. (Оранжевая линия должна быть гладкой и тоньше, но это общая идея.)

Любые идеи о создании такого отчета с помощью iReport 3.7.1?

+0

выглядит хорошо :), но я не думаю, что иРепорт имеет ту особенность – medopal

ответ

5

Одним из решений необходимы следующие элементы:

  • BezierLineCustomizer, чтобы сделать линии изогнуты.
  • RunningAverageIncrementer для расчета среднего значения на основе переменной.
  • переменная iReport, которая использует RunningAverageIncremeter.

BezierLineCustomizer Класс

public class BezierLineCustomizer 
    implements JRChartCustomizer { 
    public BezierLineCustomizer() { 
    } 

    public void customize(JFreeChart jFreeChart, JRChart jrChart) { 
    XYPlot xyPlot = (XYPlot)jFreeChart.getPlot(); 

    XYSplineRenderer splineRenderer = new XYSplineRenderer(); 

    // Make the spline line thick and orange. 
    // 
    splineRenderer.setSeriesShapesVisible(0, false); 
    splineRenderer.setSeriesShapesVisible(1, false); 
    splineRenderer.setSeriesLinesVisible(1, false); 
    splineRenderer.setSeriesStroke(
     0, new BasicStroke(
      4.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 
      1.0f, null, 0.0f 
     ) 
    ); 

    splineRenderer.setSeriesPaint(0, new Color(255, 140, 0)); 
    splineRenderer.setSeriesVisibleInLegend(1, Boolean.FALSE); 

    // Duplicate the data into a new dataset to control its line independently. 
    // 
    xyPlot.setDataset(1, xyPlot.getDataset(0)); 

    XYItemRenderer defaultRenderer = new XYLineAndShapeRenderer(); 
    defaultRenderer.setSeriesVisible(0, Boolean.FALSE); 
    defaultRenderer.setSeriesVisibleInLegend(0, Boolean.FALSE); 

    xyPlot.setRenderer(1, defaultRenderer); 
    xyPlot.setRenderer(0, splineRenderer); 
    } 
} 

RunningAverageIncrementer Класс

public class RunningAverageIncrementer 
    implements JRIncrementer { 
    /** Default number of tallies. */ 
    private static final int DEFAULT_TALLIES = 128; 

    /** Number of tallies within the sliding window. */ 
    private static final int DEFAULT_SLIDING_WINDOW_SIZE = 30; 

    /** Stores a sliding window of values. */ 
    private List<Double> values = new ArrayList<Double>(DEFAULT_TALLIES); 

    /** 
    * Instantiated by the RunningAverageIncrementerFactory class. 
    */ 
    public RunningAverageIncrementer() { 
    } 

    /** 
    * Calculates the average of previously known values. 
    * @return The average of the list of values returned by getValues(). 
    */ 
    private double calculateAverage() { 
    double result = 0.0; 
    List<Double> values = getValues(); 

    for(Double d: getValues()) { 
     result += d.doubleValue(); 
    } 

    return result/values.size(); 
    } 

    /** 
    * Called each time a new value to be averaged is received. 
    * @param value The new value to include for the average. 
    */ 
    private void recordValue(Double value) { 
    List<Double> values = getValues(); 

    // Throw out 
    // 
    if(values.size() > getSlidingWindowSize()) { 
     values.remove(0); 
    } 

    this.values.add(value); 
    } 

    private List<Double> getValues() { 
    return values; 
    } 

    private int getIterations() { 
    return getValues().size(); 
    } 

    /** 
    * Returns the newly incremented value, which is calculated by averaging 
    * the previous value from the previous call to this method. 
    * 
    * @param jrFillVariable Unused. 
    * @param tally New data point to average. 
    * @param abstractValueProvider Unused. 
    * @return The newly incremented value. 
    */ 
    public Object increment(JRFillVariable jrFillVariable, Object tally, 
          AbstractValueProvider abstractValueProvider) { 
    double value = ((Number)tally).doubleValue(); 

    recordValue(value); 

    double previousAverage = calculateAverage(); 
    double newAverage = 
     ((value - previousAverage)/(getIterations() + 1)) + previousAverage; 

    return new BigDecimal(newAverage); 
    } 

    protected int getSlidingWindowSize() { 
    return DEFAULT_SLIDING_WINDOW_SIZE; 
    } 
} 

иРепорт Переменная

Создать переменную который использует класс RunningAverageIncrementerFactory (упражнение слева от читателя). Задайте переменное выражение на построенное значение. Задайте значение его начального значения равным нулю.

сплайн

Установите Customizer Класс свойство TimeSeries картировать использовать BezierLineCustomizer класс.

Результат

После этих изменений, скользящее среднее отчетливо видно:

Смежные вопросы