Jfreechart 注释消失 [英] Jfreechart annotations disappearing

查看:26
本文介绍了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.

按照建议,我准备了一个 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 是在按下鼠标按钮时拍摄的.

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

  1. 选择几条不重叠的线 - 应该没问题

<小时>

我刚刚在调试器中查看它 - ArrayList.remove(Object o) 会删除 WRONG 元素吗?对我来说似乎不太可能...


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...

推荐答案

您可以查看 Layer 注释被添加到其中.这里有一个示例.当然,展示您描述的问题的 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.

附录:一个潜在的问题是您对 Comparableequals() 不一致,因为后者(隐式)依赖于超类实现.与已排序的 Set(例如 TreeSet)一起使用需要一致的实现.您还需要覆盖 hashCode().Value 类就是一个例子.

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天全站免登陆