2012-01-24 87 views
1

我用JFreechart繪製曲線。然後用戶可以通過拖動鼠標來繪製範圍。這些我使用AbstractChartAnnotation繪製一個填充的Path2D。到目前爲止非常好 - 所有曲線都完美對齊。Jfreechart註釋消失

當某個區域已被註釋時,新的註釋將被刪除。我使用XYPlot.removeAnnotation和新的註釋。

我的問題是,有時不僅「新」註釋被刪除,而且還在繪圖中的其他註釋。它看起來並不隨意 - 我發現對「正確」一側的註釋更容易發生這種情況。

我很困惑什麼會導致這種情況。每次恢復繪製/刪除新註釋的對象並僅保留當前註釋 - 那麼如何刪除其他註釋?

將非常感謝任何提示,謝謝。


建議我準備一個sscce的例子。不幸的是它不是太短。

import java.awt.*; 
import java.awt.event.MouseEvent; 
import java.awt.geom.AffineTransform; 
import java.awt.geom.Line2D; 
import java.awt.geom.Point2D; 
import java.awt.geom.Rectangle2D; 
import java.util.*; 
import java.util.List; 
import javax.swing.JFrame; 
import javax.swing.event.MouseInputListener; 
import org.jfree.chart.ChartFactory; 
import org.jfree.chart.ChartPanel; 
import org.jfree.chart.JFreeChart; 
import org.jfree.chart.annotations.AbstractXYAnnotation; 
import org.jfree.chart.axis.ValueAxis; 
import org.jfree.chart.plot.Plot; 
import org.jfree.chart.plot.PlotOrientation; 
import org.jfree.chart.plot.PlotRenderingInfo; 
import org.jfree.chart.plot.XYPlot; 
import org.jfree.data.time.Millisecond; 
import org.jfree.data.time.TimeSeries; 
import org.jfree.data.time.TimeSeriesCollection; 
import org.jfree.data.time.TimeSeriesDataItem; 
import org.jfree.ui.RectangleEdge; 

/** 
* 
* @author c.ager 
*/ 
public class IntegrationSSCE { 

    /** 
    * @param args the command line arguments 
    */ 
    public static void main(String[] args) { 
     JFrame jFrame = new JFrame(); 
     jFrame.setLayout(new BorderLayout()); 
     jFrame.setSize(600, 400); 
     jFrame.setDefaultCloseOperation(jFrame.EXIT_ON_CLOSE); 
     TimeSeriesCollection timeSeriesCollection = new TimeSeriesCollection(); 
     TimeSeries timeSeries = new TimeSeries("test"); 
     for (long i = 0; i < 1000; i++) { 
      double val = Math.random() + 3 * Math.exp(-Math.pow(i - 300, 2)/1000); 
      timeSeries.add(new Millisecond(new Date(i)), val); 
     } 
     timeSeriesCollection.addSeries(timeSeries); 

     JFreeChart chart = ChartFactory.createTimeSeriesChart(
       null, 
       null, "data", timeSeriesCollection, 
       true, true, false); 
     ChartPanel chartPanel = new ChartPanel(chart); 
     chartPanel.removeMouseListener(chartPanel); 

     Set<MyAnnot> annotSet = new TreeSet<MyAnnot>(); 

     AnnotListener list = new AnnotListener(chartPanel, annotSet, timeSeries); 
     chartPanel.addMouseListener(list); 
     chartPanel.addMouseMotionListener(list); 

     jFrame.add(chartPanel, BorderLayout.CENTER); 


     jFrame.setVisible(true); 

     // TODO code application logic here 
    } 

    private static class AnnotListener implements MouseInputListener { 

     Point2D start, end; 
     MyAnnot currAnnot; 
     final Set<MyAnnot> annotSet; 
     final ChartPanel myChart; 
     final TimeSeries timeSeries; 

     public AnnotListener(ChartPanel myChart, Set<MyAnnot> annotSet, TimeSeries timeSeries) { 
      this.myChart = myChart; 
      this.annotSet = annotSet; 
      this.timeSeries = timeSeries; 
     } 

     @Override 
     public void mousePressed(MouseEvent e) { 
      start = convertScreePoint2DataPoint(e.getPoint()); 
      currAnnot = new MyAnnot(start, timeSeries, myChart.getChart().getXYPlot()); 
      myChart.getChart().getXYPlot().addAnnotation(currAnnot); 
     } 

     @Override 
     public void mouseDragged(MouseEvent e) { 
      end = convertScreePoint2DataPoint(e.getPoint()); 
      currAnnot.updateEnd(end); 
     } 

     @Override 
     public void mouseReleased(MouseEvent e) { 
      boolean test = annotSet.add(currAnnot); 
      if (!test) { 
       myChart.getChart().getXYPlot().removeAnnotation(currAnnot); 
      } 
     } 

     @Override 
     public void mouseEntered(MouseEvent e) { 
     } 

     @Override 
     public void mouseClicked(MouseEvent e) { 
     } 

     @Override 
     public void mouseExited(MouseEvent e) { 
     } 

     @Override 
     public void mouseMoved(MouseEvent e) { 
     } 

     protected Point2D convertScreePoint2DataPoint(Point in) { 
      Rectangle2D plotArea = myChart.getScreenDataArea(); 
      XYPlot plot = (XYPlot) myChart.getChart().getPlot(); 
      double x = plot.getDomainAxis().java2DToValue(in.getX(), plotArea, plot.getDomainAxisEdge()); 
      double y = plot.getRangeAxis().java2DToValue(in.getY(), plotArea, plot.getRangeAxisEdge()); 
      return new Point2D.Double(x, y); 
     } 
    } 

    private static class MyAnnot extends AbstractXYAnnotation implements Comparable<MyAnnot> { 

     Long max; 
     Line2D line; 
     final TimeSeries timeSeries; 
     final XYPlot plot; 
     final Stroke stroke = new BasicStroke(1.5f); 

     public MyAnnot(Point2D start, TimeSeries timeSeries, XYPlot plot) { 
      this.plot = plot; 
      this.timeSeries = timeSeries; 

      line = new Line2D.Double(start, start); 
      findMax(); 
     } 

     public void updateEnd(Point2D end) { 
      line.setLine(line.getP1(), end); 
      findMax(); 
      fireAnnotationChanged(); 
     } 

     @Override 
     public void draw(Graphics2D gd, XYPlot xyplot, Rectangle2D rd, ValueAxis va, ValueAxis va1, int i, PlotRenderingInfo pri) { 
      PlotOrientation orientation = plot.getOrientation(); 
      RectangleEdge domainEdge = Plot.resolveDomainAxisLocation(
        plot.getDomainAxisLocation(), orientation); 
      RectangleEdge rangeEdge = Plot.resolveRangeAxisLocation(
        plot.getRangeAxisLocation(), orientation); 

      double m02 = va.valueToJava2D(0, rd, domainEdge); 
      // y-axis translation 
      double m12 = va1.valueToJava2D(0, rd, rangeEdge); 
      // x-axis scale 
      double m00 = va.valueToJava2D(1, rd, domainEdge) - m02; 
      // y-axis scale 
      double m11 = va1.valueToJava2D(1, rd, rangeEdge) - m12; 

      Shape s = null; 
      if (orientation == PlotOrientation.HORIZONTAL) { 
       AffineTransform t1 = new AffineTransform(
         0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f); 
       AffineTransform t2 = new AffineTransform(
         m11, 0.0f, 0.0f, m00, m12, m02); 
       s = t1.createTransformedShape(line); 
       s = t2.createTransformedShape(s); 
      } else if (orientation == PlotOrientation.VERTICAL) { 
       AffineTransform t = new AffineTransform(m00, 0, 0, m11, m02, m12); 
       s = t.createTransformedShape(line); 
      } 
      gd.setStroke(stroke); 
      gd.setPaint(Color.BLUE); 
      gd.draw(s); 
      addEntity(pri, s.getBounds2D(), i, getToolTipText(), getURL()); 
     } 

     @Override 
     public int compareTo(MyAnnot o) { 
      return max.compareTo(o.max); 
     } 

     private void findMax() { 
      max = (long) line.getP1().getX(); 

      Point2D left, right; 
      if (line.getP1().getX() < line.getP2().getX()) { 
       left = line.getP1(); 
       right = line.getP2(); 
      } else { 
       left = line.getP2(); 
       right = line.getP1(); 
      } 
      Double maxVal = left.getY(); 
      List<TimeSeriesDataItem> items = timeSeries.getItems(); 
      for (Iterator<TimeSeriesDataItem> it = items.iterator(); it.hasNext();) { 
       TimeSeriesDataItem dataItem = it.next(); 
       if (dataItem.getPeriod().getFirstMillisecond() < left.getX()) { 
        continue; 
       } 
       if (dataItem.getPeriod().getFirstMillisecond() > right.getX()) { 
        break; 
       } 
       double curVal = dataItem.getValue().doubleValue(); 
       if (curVal > maxVal) { 
        maxVal = curVal; 
        max = dataItem.getPeriod().getFirstMillisecond(); 
       } 
      } 
     } 
    } 
} 

這是有問題的行爲。請注意,圖像2和4是在按下鼠標按鈕時拍攝的。

  1. 選擇一些非重疊線路 - 沒問題,因爲它應該是 select a few non-overlapping lines enter image description here enter image description here enter image description here enter image description here

我在調試器只是一直看着它 - ArrayList.remove(Object o)是否可以刪除WRONG元素?似乎不太可能...

+0

+1表示sscce。 – trashgod

回答

2

你可能會看看添加了註釋的Layer。有一個例子here。當然,顯示你描述的問題的sscce將有助於澄清問題的根源。

附錄:一個潛在的問題是,你的Comparable實施equals()一致,因爲後者依賴(隱含的)的超類的實現。與排序的Set(如TreeSet)一起使用需要一致的實現。您也需要覆蓋hashCode()。類​​就是一個例子。

+0

Ok創建了一個sscce。但無法找到該圖層。你能指點我嗎? – bdecaf

+0

如果您有權訪問[_ Effective Java_](http://java.sun.com/docs/books/effective/),請參閱項目9和12. – trashgod

+0

啊 - 我們正在某處!重載hashCode本身並沒有幫助 - 但我得到了一條消息,我應該重寫'equals',現在我沒有看到示例中的「奇怪」行爲。不幸的是,我無法訪問您建議的書。你建議的章節對待什麼? – bdecaf