2010-03-16 222 views
4

除了顯示數據點之外,您將如何在JasperReports中創建一條跟隨數據趨勢的行?以下是之前和拍攝後:報告趨勢線

之前

時間序列報告似乎並未有任何這樣的選項來繪製橙色線後。 (橙色線應該平滑,更細,但這是一般想法。)

任何想法如何製作這樣的報告與iReport 3.7.1?

+0

看起來不錯:),但我不認爲iReport的具有該功能 – medopal

回答

5

一種解決方案需要以下項目:

  • BezierLineCustomizer使線彎曲。
  • RunningAverageIncrementer基於變量計算運行平均值。
  • 使用RunningAverageIncremeter的iReport變量。

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

iReport的可變

創建一個變量使用RunningAverageIncrementerFactory類(向讀者行使)。將其變量表達式設置爲繪圖值。將其初始值表達式設置爲零。

樣條

設置時間序列的定製類屬性圖表使用BezierLineCustomizer類。

結果

這些修改後,運行平均清晰可見: