2011-11-03 44 views
3

我已經堆積了條形圖,我希望能夠選擇堆棧中的單個條形圖。但ChartMouseListener不會將ChartMouseEvent解析爲相應的ChartEntity。這裏的聽衆片段:JFreeChart MouseListener不能解析圖表元素

public void chartMouseClicked(ChartMouseEvent event){ 
     ChartEntity entity = event.getEntity(); 
     if(entity != null && (entity instanceof XYItemEntity)){ 
      XYItemEntity item = (XYItemEntity)entity; 
      renderer.select(item.getSeriesIndex(), item.getItem()); 
      return; 
     } 

     // deselect 
     renderer.select(-1,-1); 
    } 

的問題是,event.getEntity()返回null時,我明明點擊的一些酒吧。請注意,並非所有的酒吧都失敗。我進一步走到圖表的右端,更明顯的是座標的移位。下方的快照顯示在點擊外部時選定的欄實際出現的位置。我在SWT組合中使用JFreeChart。任何人都可以證實,這是一個馬車行爲或是否有解決方法

enter image description here

下面是完整的SSCCE,你運行它,點擊後槓 - 它會顯示小指。然後重新調整窗口大小並嘗試選擇酒吧 - 它會錯過。我認爲這個小姐是新尺寸的功能。

import java.awt.Color; 
import java.awt.Paint; 
import java.util.Random; 

import org.eclipse.swt.SWT; 
import org.eclipse.swt.layout.FillLayout; 
import org.eclipse.swt.layout.GridData; 
import org.eclipse.swt.widgets.Display; 
import org.eclipse.swt.widgets.Shell; 
import org.jfree.chart.ChartMouseEvent; 
import org.jfree.chart.ChartMouseListener; 
import org.jfree.chart.JFreeChart; 
import org.jfree.chart.axis.DateAxis; 
import org.jfree.chart.axis.DateTickMarkPosition; 
import org.jfree.chart.axis.NumberAxis; 
import org.jfree.chart.entity.ChartEntity; 
import org.jfree.chart.entity.XYItemEntity; 
import org.jfree.chart.event.RendererChangeEvent; 
import org.jfree.chart.plot.XYPlot; 
import org.jfree.chart.renderer.xy.StackedXYBarRenderer; 
import org.jfree.chart.renderer.xy.StandardXYBarPainter; 
import org.jfree.data.time.Day; 
import org.jfree.data.time.Hour; 
import org.jfree.data.time.TimeTableXYDataset; 
import org.jfree.data.xy.TableXYDataset; 
import org.jfree.experimental.chart.swt.ChartComposite; 

public class StackedChartSwt { 
    private StackedRenderer renderer; 
    private Color[] colors = new Color[]{ 
      new Color(230,240,255), 
      new Color(240,255,240), 
      new Color(255,255,255), 
      new Color(255,255,240), 
      new Color(255,240,240), 
      new Color(240,240,240) 
    }; 

    public StackedChartSwt(){ 
     Display display = new Display(); 
     final Shell shell = new Shell(display); 
     shell.setLayout(new FillLayout()); 

     JFreeChart chart = createStackedChart(createStackedDataset()); 
     ChartComposite chartComposite = new ChartComposite(shell, SWT.NONE, chart, false, false, false, false, false); 
     chartComposite.setLayoutData(new GridData(GridData.FILL_BOTH)); 
     chartComposite.setRangeZoomable(false); 
     chartComposite.setMenu(null); 
     chartComposite.addChartMouseListener(new ThisMouseListener()); 
     shell.setSize(800, 600); 
     shell.open(); 

     while (!shell.isDisposed()) { 
      if (!display.readAndDispatch()) { 
       display.sleep(); 
      } 
      } 

      display.dispose();   
    } 

    private JFreeChart createStackedChart(TableXYDataset tablexydataset) { 
     DateAxis dateaxis = new DateAxis(); 
     dateaxis.setTickMarkPosition(DateTickMarkPosition.MIDDLE); 
     NumberAxis numberaxis = new NumberAxis("Event counts"); 
     renderer = new StackedRenderer(); 
     XYPlot plot = new XYPlot(tablexydataset, dateaxis, numberaxis, renderer); 
     plot.setBackgroundPaint(Color.white); 
     plot.setDomainGridlinePaint(Color.lightGray); 
     plot.setDomainGridlinesVisible(true); 
     plot.setRangeGridlinesVisible(true); 
     plot.setRangeGridlinePaint(Color.lightGray); 

     JFreeChart chart = new JFreeChart(null, plot); 
     chart.setBackgroundPaint(Color.white); 
     chart.setBorderVisible(false); 
     chart.setBorderPaint(null); 

     return chart; 
    } 

    class StackedRenderer extends StackedXYBarRenderer{ 
     int selectedRow=-1, selectedCol=-1; 
     public StackedRenderer(){ 
      setDrawBarOutline(true); 
      setBarPainter(new StandardXYBarPainter()); 
      setShadowVisible(false); 
      setSeriesPaint(0, Color.blue); 
      setMargin(0.2); 
     } 

     public void select(int row, int col){ 
      selectedRow = row; 
      selectedCol = col; 
      notifyListeners(new RendererChangeEvent(this)); 
     } 

     @Override 
     public Paint getItemPaint(final int row, final int col){ 
      if(row == selectedRow && col == selectedCol) 
       return Color.pink; 
      return colors[row]; 
     } 
    } 

    class ThisMouseListener implements ChartMouseListener{ 
     public void chartMouseMoved(ChartMouseEvent event){ 
     } 

     public void chartMouseClicked(ChartMouseEvent event){ 
      ChartEntity entity = event.getEntity(); 
      if(entity != null && (entity instanceof XYItemEntity)){ 
       XYItemEntity item = (XYItemEntity)entity; 
       renderer.select(item.getSeriesIndex(), item.getItem()); 
       return; 
      } 

      // deselect 
      renderer.select(-1,-1); 
     } 
    } 

    private TableXYDataset createStackedDataset(){ 
     Random random = new Random(0); 
     TimeTableXYDataset ds = new TimeTableXYDataset(); 
     Day day = new Day(); 
     for(int i = 0; i < 24; i++){ 
      Hour hour = new Hour(i, day); 
      ds.add(hour, random.nextInt(20), "A"); 
      ds.add(hour, random.nextInt(20), "B"); 
      ds.add(hour, random.nextInt(20), "C"); 
      ds.add(hour, random.nextInt(20), "D"); 
      ds.add(hour, random.nextInt(20), "E"); 
      ds.add(hour, random.nextInt(20), "F"); 
     } 

     return ds; 
    } 

    public static void main(String[] args){ 
     new StackedChartSwt(); 
    } 
} 
+0

請提供[sscce](http://sscce.org/),展示您描述的問題。 – trashgod

+0

@trashgod - 添加sscce,您可以運行它並單擊(重新調整窗口大小以查看問題) – Dima

+0

+1 [sscce](http://sscce.org/);以及很好的粉彩。 :-) – trashgod

回答

4

OK,我已經找到了問題。在SWT中,有幾個構造函數可以創建ChartComposite,大多數使用默認值指定最小/最大寬度和高度。在我的情況下,每當我放大DEFAULT_MAXIMUM_DRAW_WIDTH(800px)以上的圖表時 - 座標開始變得混亂。所以,解決方案是使用完整的構造函數併爲您的顯示指定相關邊界。這是一個很難解決的問題......主要是由於缺乏適當的文件。

3

從Swing運行時,您的示例性渲染器具有正確的幾何圖形,如下所示。我不確定爲什麼SWT會出現錯誤,但是這個結果可能會縮小搜索範圍。

enter image description here

import java.awt.Color; 
import java.awt.EventQueue; 
import java.awt.Paint; 
import java.util.Random; 
import javax.swing.JFrame; 
import org.jfree.chart.ChartMouseEvent; 
import org.jfree.chart.ChartMouseListener; 
import org.jfree.chart.ChartPanel; 
import org.jfree.chart.JFreeChart; 
import org.jfree.chart.axis.DateAxis; 
import org.jfree.chart.axis.DateTickMarkPosition; 
import org.jfree.chart.axis.NumberAxis; 
import org.jfree.chart.entity.ChartEntity; 
import org.jfree.chart.entity.XYItemEntity; 
import org.jfree.chart.event.RendererChangeEvent; 
import org.jfree.chart.plot.XYPlot; 
import org.jfree.chart.renderer.xy.StackedXYBarRenderer; 
import org.jfree.chart.renderer.xy.StandardXYBarPainter; 
import org.jfree.data.time.Day; 
import org.jfree.data.time.Hour; 
import org.jfree.data.time.TimeTableXYDataset; 
import org.jfree.data.xy.TableXYDataset; 

public class StackedChartSwing { 

    private ChartPanel panel; 
    private StackedRenderer renderer; 
    private Color[] colors = new Color[]{ 
     new Color(230, 240, 255), 
     new Color(240, 255, 240), 
     new Color(255, 255, 255), 
     new Color(255, 255, 240), 
     new Color(255, 240, 240), 
     new Color(240, 240, 240) 
    }; 

    public StackedChartSwing() { 
     JFreeChart chart = createStackedChart(createStackedDataset()); 
     panel = new ChartPanel(chart); 
     panel.addChartMouseListener(new ThisMouseListener()); 
    } 

    private JFreeChart createStackedChart(TableXYDataset tablexydataset) { 
     DateAxis dateaxis = new DateAxis(); 
     dateaxis.setTickMarkPosition(DateTickMarkPosition.MIDDLE); 
     NumberAxis numberaxis = new NumberAxis("Event counts"); 
     renderer = new StackedRenderer(); 
     XYPlot plot = new XYPlot(tablexydataset, dateaxis, numberaxis, renderer); 
     plot.setBackgroundPaint(Color.white); 
     plot.setDomainGridlinePaint(Color.lightGray); 
     plot.setDomainGridlinesVisible(true); 
     plot.setRangeGridlinesVisible(true); 
     plot.setRangeGridlinePaint(Color.lightGray); 

     JFreeChart chart = new JFreeChart(null, plot); 
     chart.setBackgroundPaint(Color.white); 
     chart.setBorderVisible(false); 
     chart.setBorderPaint(null); 

     return chart; 
    } 

    class StackedRenderer extends StackedXYBarRenderer { 

     int selectedRow = -1, selectedCol = -1; 

     public StackedRenderer() { 
      setDrawBarOutline(true); 
      setBarPainter(new StandardXYBarPainter()); 
      setShadowVisible(false); 
      setSeriesPaint(0, Color.blue); 
      setMargin(0.2); 
     } 

     public void select(int row, int col) { 
      selectedRow = row; 
      selectedCol = col; 
      notifyListeners(new RendererChangeEvent(this)); 
     } 

     @Override 
     public Paint getItemPaint(final int row, final int col) { 
      if (row == selectedRow && col == selectedCol) { 
       return Color.pink; 
      } 
      return colors[row]; 
     } 
    } 

    class ThisMouseListener implements ChartMouseListener { 

     @Override 
     public void chartMouseMoved(ChartMouseEvent event) { 
     } 

     @Override 
     public void chartMouseClicked(ChartMouseEvent event) { 
      ChartEntity entity = event.getEntity(); 
      if (entity != null && (entity instanceof XYItemEntity)) { 
       XYItemEntity item = (XYItemEntity) entity; 
       renderer.select(item.getSeriesIndex(), item.getItem()); 
       return; 
      } 
      // deselect 
      renderer.select(-1, -1); 
     } 
    } 

    private TableXYDataset createStackedDataset() { 
     Random random = new Random(0); 
     TimeTableXYDataset ds = new TimeTableXYDataset(); 
     Day day = new Day(); 
     for (int i = 0; i < 24; i++) { 
      Hour hour = new Hour(i, day); 
      ds.add(hour, random.nextInt(20), "A"); 
      ds.add(hour, random.nextInt(20), "B"); 
      ds.add(hour, random.nextInt(20), "C"); 
      ds.add(hour, random.nextInt(20), "D"); 
      ds.add(hour, random.nextInt(20), "E"); 
      ds.add(hour, random.nextInt(20), "F"); 
     } 

     return ds; 
    } 

    private void display() { 
     JFrame f = new JFrame("Test"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.add(panel); 
     f.pack(); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       new StackedChartSwing().display(); 
      } 
     }); 
    } 
} 
+0

@Dima:作爲參考,我得到了一個類似的,正確的結果,添加一個'ChartMouseListener'到['BarChartDemo1'](http://www.jfree.org/jfreechart/api/javadoc/org/jfree/chart /demo/BarChartDemo1.html)下的Swing。 – trashgod

+0

是的,擺動在這裏不是問題。問題出現在JFreeChart的SWT版本中。事實上,當最初打開時,一切正常。但只要您重新設置主機框架的大小,事情就會變得瘋狂。它必須是非常簡單的東西,就像圖表不知道它被調整大小一樣..但它確實吸引了它自己,它只是渲染器變得毫無用處。我需要這些東西在eclipse RCP應用程序中工作,如果不能修復,那該多麼慚愧,所有的庫變得無效。 – Dima