JFreeChart的注释消失 [英] Jfreechart annotations disappearing

查看:306
本文介绍了JFreeChart的注释消失的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我绘制了使用JFreeChart的曲线。然后,用户可以通过拖动鼠标绘制范围。使用AbstractChartAnnotation这些情节我画一个充满Path2D。到目前为止,这么好看 - 所有与曲线完全对齐

I plot a curve with JFreechart. Then the user can draw ranges by dragging the mouse. These I plot using AbstractChartAnnotation to draw a filled Path2D. So far so nice - all aligns perfectly with the curve.

当一个地区已经诠释了新的注释被删除。我使用 XYPlot.removeAnnotation 通过新的诠释。

When an area was already annotated the new annotation gets deleted. I use XYPlot.removeAnnotation with the new annotation.

我的问题是,有时不仅是新的注释被删除,但还有第二批注中的情节在其他地方。这似乎不是随机的 - 我还挺找到注解右侧更容易出现这种情况的发生。

My problem is that sometimes not only the "new" annotation gets removed, but also a second annotation elsewhere in the plot. It doesn't seem random - I kinda found annotations to the "right" side more prone to this happening.

我很困惑这是什么原因。绘制对象/删除新的注解恢复每次只有保持当前的注释 - ?怎么可能其他的注释被删除

I'm very confused what could cause this. The object that draws/deletes the new annotation is reinstated every time and only holds the current annotation - so how could the other annotation be deleted?

将非常感谢任何提示,谢谢。

Would be very grateful for any hints, thanks.

至于建议我prepare一个SSCCE例子。可惜这不是太短了。

As suggested I prepare a sscce example. Unfortunately it's not too short.

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拍摄,而鼠标按键pressed。

Here is the problematic behaviour. Note that images 2 and 4 were taken while the mouse button was pressed.


  1. 选择一些非重叠行 - 没问题,因为它应该是





我刚才一直在调试器看着它 - 它可能是ArrayList.remove(对象o)删除了错误的元素?似乎不太可能,我...


I have just been looking at it in the debugger - could it be that ArrayList.remove(Object o) removes the WRONG element? Seems very unlikely to me...

推荐答案

您可能看的 图层 它被添加到注释。这里这里有一个例子。当然,一个 SSCCE 显示出您所描述的问题将有助于澄清问题的根源。

You might look at the Layer to which the annotation is being added. There's an example here. Naturally, an sscce that exhibits the problem you describe would help clarify the source of the problem.

附录:一个潜在的问题是,你的实施可比 是的的有一致的equals(),因为后者依赖(隐含的)的超类的实现。一致的实施需要一个排序的使用集 TreeSet的。你需要重写散code(),太。 就是一个例子。

Addendum: One potential problem is that your implementation of Comparable is not consistent with equals(), as the latter relies (implicitly) on the super-class implementation. A consistent implementation is required for use with a sorted Set such as TreeSet. You'll need to override hashCode(), too. Class Value is an example.

这篇关于JFreeChart的注释消失的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆