2012-01-11 84 views
0

我負責維護一個可以使用JFreeChart繪製圖形的應用程序。 該應用程序使用Eclipse-RCP和SWT編寫,並使用ChartComposite來顯示圖表。JfreeChart限制顯示的圖例項數

的ChartComposite是爲了定義取決於選擇上下文菜單被部分覆蓋:

@Override 
    public void createPartControl(Composite parent) { 
    super.createPartControl(parent); 

    chart = createChart(timeSeriesDataset); 

    chartComposite = new MyChartComposite(this, parent, SWT.NONE, chart, true); 
    chartComposite.setLayoutData(new GridData(GridData.FILL_BOTH)); 

    selectionProvider = new GenericObjectSelectionProvider(); 
    getSite().setSelectionProvider(selectionProvider); 

    // add information to the status line: 
    selectionProvider.addSelectionChangedListener(statusLineListener); 

    addDropSupport();// add D'n D support for dropping TimeSeries 

} 


protected JFreeChart createChart(TimeSeriesCollection ptimeSeriesDataset) { 

     JFreeChart vChart = ChartFactory.createTimeSeriesChart(null, "time", "values", ptimeSeriesDataset, true, 
       false, false); 
     vChart.setBackgroundPaint(Color.white); 

     XYPlot plot = vChart.getXYPlot(); 
     plot.setBackgroundPaint(Color.lightGray); 
     plot.setDomainGridlinePaint(Color.white); 
     plot.setRangeGridlinePaint(Color.white); 
     // plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0)); 
     plot.setDomainCrosshairVisible(true); 
     plot.setRangeCrosshairVisible(true); 

     plot.setRenderer(new /*OptimisedXYLineAndShapeRenderer()*/ StandardXYItemRendererFast()); 
     XYItemRenderer renderer = plot.getRenderer(); 
     renderer.setBaseToolTipGenerator(new MyXYSeriesToolTipGenerator()); 
     renderer.setBaseItemLabelGenerator(new MyXYSeriesItemLabelGenerator()); 
     renderer.setLegendItemLabelGenerator(new MyXYSeriesLegendItemLabelGenerator()); 
     if (renderer instanceof XYLineAndShapeRenderer) { 
      XYLineAndShapeRenderer r = (XYLineAndShapeRenderer) renderer; 
      r.setBaseShapesVisible(false); 
      r.setBaseShapesFilled(true); 
     } 

     SimpleDateFormat dateFormat = getDateFormatAbscissa(); 
     if (dateFormat != null){ 
      DateAxis axis = (DateAxis) plot.getDomainAxis(); 
      axis.setDateFormatOverride(dateFormat); 
     } 

     return vChart; 
    } 

我的問題是,當太多的變量添加到圖表(一TimeSeriesChart)的標題太花

ChartComposite with 2 series

ChartComposite many series

:空間和圖形從視圖中消失

我試圖創建一個ScrollComposite在ChartComposite中滾動,結果稍好一些;但它只能夠在標題中添加更多項目前的圖形再次消失:

ScrolledComposite scrollableChart = new ScrolledComposite(parent, SWT.BORDER|SWT.V_SCROLL); 

chartComposite = new MyChartComposite(this, scrollableChart, SWT.NONE, chart, true); 
//chartComposite = new MyChartComposite(this, parent, SWT.NONE, chart, true); 
//chartComposite.setLayoutData(new GridData(GridData.FILL_BOTH)); 

scrollableChart.setContent(chartComposite); 
scrollableChart.setExpandVertical(true); 
scrollableChart.setExpandHorizontal(true); 
scrollableChart.setMinSize(ChartComposite.DEFAULT_MINIMUM_DRAW_WIDTH, ChartComposite.DEFAULT_MINIMUM_DRAW_WIDTH); 

我的問題是:如何提供一個真正的滾動條到ChartComposite爲了保持圖形時,多系列繪製在圖上?

回答

2

我能夠通過使用FormData使用ChartComosite和Slider對象將滑塊同步到SWT中的XYSeries。每當我移動滑塊時,我都會根據自己的需要捕獲該事件並自行更新圖表。

我的用例可能與您的用例不同,但值得看一下我的回答here

如果您對我的實現,在這個問題的答案描述的問題,隨意詢問詳情

+0

謝謝,我只是找到了你的帖子在幾個小時前,我會盡量解決方案適應我的需要。 – zeropouet 2012-01-12 14:56:57

1

幾次不成功的嘗試後,我決定限制在圖表上顯示的LegendItem數量。

要更改圖例項目以顯示在LegendTitle我使用了滑塊。最難的部分是在使用滑塊時重新創建一個新的LegendTitle;我不確定我的解決方案是最優的還是優雅的,但至少它工作正常。

Result

要做到這一點,我需要聽系列創建(ChartChangeEventType.DATASET_UPDATED)刷新LegendTitle並設置滑塊值。

所以這裏是代碼:

public class MyExampleChartComposite extends ChartComposite { 
    // snip 
    /** 
    * A slider to choose the legend items to display 
    */ 
    private Slider legendSlider; 
    /** 
    * Number of legend items to display on the chart 
    */ 
    private final static int NUMBER_OF_LEGENDITEMS_TO_DISPLAY = 10; 

    private void createPartControl(Composite parent, int style) { 
     JFreeChart chart = createChart(); 
     setChart(chart); 
     legendSlider = new Slider(parent, SWT.NONE|SWT.H_SCROLL); 
     legendSlider.addSelectionListener(new SelectionListener() { 
      @Override 
      public void widgetSelected(SelectionEvent arg0) { 
         refreshLegend(); 
      } 
     }); 

    private JFreeChart createChart() { 
     chart.addChangeListener(new ChartChangeListener() {  
      @Override 
      public void chartChanged(ChartChangeEvent e) { 
        if (e.getType().equals(ChartChangeEventType.DATASET_UPDATED)) { 
         refreshLegend(); 
        } 
      } 
     }); 
    } 

    /** 
    * Refresh the the LegendItems and the slider, 
    * according to slider selection. 
    */ 
    public void refreshLegend() { 
     // Display LegendItems according to the selection 
     // display the 10 nearest legend item (current selected element included) 
     int begin = legendSlider.getSelection() - (NUMBER_OF_LEGENDITEMS_TO_DISPLAY/2); 
     int end = legendSlider.getSelection() + (NUMBER_OF_LEGENDITEMS_TO_DISPLAY/2 -1); 
     int seriesEndIndex = Math.max(getSeriesCount()-1, 0); 
     // if begin is less than 0 
     // set it to 0, and increase end to display 10 items 
     if (begin < 0) { 
      begin = 0; 
      end = NUMBER_OF_LEGENDITEMS_TO_DISPLAY - 1; 
     } 
     // if end is greater than the number of series plotted 
     // set it to the max possible value and increase begin to 
     // display 10 items 
     if (end > seriesEndIndex) { 
      end = seriesEndIndex; 
      begin = seriesEndIndex - (NUMBER_OF_LEGENDITEMS_TO_DISPLAY - 1); 
     } 
     end = Math.min(seriesEndIndex, end); 
     begin = Math.max(begin, 0); 
     // Refresh only if begin != end 
     if (end != begin) { 
      refreshLegendItems(begin, end); 
      refreshLegendSlider(); 
     } else { 
      // in this case no more series are plotted on the chart 
      // clear legend 
      getChart().clearSubtitles(); 
     } 
    } 
    /** 
    * Refresh the LegendTitle. 
    * Display only LegendItems between beginIndex and toIndex, 
    * to preserve space for the chart. 
    * @param beginIndex index of the {@link LegendItemCollection} used as the beginning of the new {@link LegendTitle} 
    * @param endIndex index of the {@link LegendItemCollection} used as the end of the new {@link LegendTitle} 
    */ 
    private void refreshLegendItems(int beginIndex, int endIndex) { 
     // Last 10 items 
     final LegendItemCollection result = new LegendItemCollection(); 
     // get the renderer to retrieve legend items 
     XYPlot plot = getChart().getXYPlot(); 
     XYItemRenderer renderer = plot.getRenderer(); 
     // Number of series displayed on the chart 
     // Construct the legend 
     for (int i = beginIndex; i <= endIndex; i++) { 
      LegendItem item = renderer.getLegendItem(0, i); 
      result.add(item); 
     } 
     // Because the only way to create a new LegendTitle is to 
     // create a LegendItemSource first 
     LegendItemSource source = new LegendItemSource() { 
      LegendItemCollection lic = new LegendItemCollection(); 
      {lic.addAll(result);} 
      public LegendItemCollection getLegendItems() { 
       return lic; 
      } 
     }; 
     // clear previous legend title 
     getChart().clearSubtitles(); 
     // Create the new LegendTitle and set its position 
     LegendTitle legend = new LegendTitle(source); 
     legend.setHorizontalAlignment(HorizontalAlignment.CENTER); 
     legend.setVerticalAlignment(VerticalAlignment.CENTER); 
     legend.setPosition(RectangleEdge.BOTTOM); 
     legend.setBorder(1.0, 1.0, 1.0, 1.0); 
     legend.setVisible(true); 
     // Add the LegendTitle to the graph 
     getChart().addLegend(legend); 
    } 

    /** 
    * Set values of the slider according to the number of series 
    * plotted on the graph 
    */ 
    private void refreshLegendSlider() { 
     int max = getSeriesCount() -1; 
     int selection = Math.min(legendSlider.getSelection(), max); 
     legendSlider.setValues(selection, 0, max, 1, 1, 1); 
    } 
} 
+0

我的問題與你的完全不同,但我能夠使用你分享的有關這些JFree類(尤其是'LegendTitle'和'LegendItemSource')的見解。非常感謝! – 2012-09-04 14:45:38