Create a marker / crosshair in a CombinedDomainXYPlot

后端 未结 2 1341
梦如初夏
梦如初夏 2021-01-23 15:18

I want to show in a CombinedDomainXYPlot a marker. This is not working. I can add the marker for each subplot. But I want to add it for the CombinedDomainXYPlot. Anybody who can

2条回答
  •  醉话见心
    2021-01-23 15:53

    Thanks to Graham I developed an adjusted version of CombinedDomainXYPlot, which works for me. The result looks like this.

    CombinedDomainXYPlot with Marker

    I merged Code from XYPlot and XYLineAndShapeRenderer to achieve this. Here is the source code.

    import java.awt.AlphaComposite;
    import java.awt.Composite;
    import java.awt.Font;
    import java.awt.GradientPaint;
    import java.awt.Graphics2D;
    import java.awt.Paint;
    import java.awt.geom.Line2D;
    import java.awt.geom.Point2D;
    import java.awt.geom.Rectangle2D;
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    
    import org.jfree.chart.annotations.XYAnnotation;
    import org.jfree.chart.axis.ValueAxis;
    import org.jfree.chart.plot.CombinedDomainXYPlot;
    import org.jfree.chart.plot.IntervalMarker;
    import org.jfree.chart.plot.Marker;
    import org.jfree.chart.plot.PlotOrientation;
    import org.jfree.chart.plot.PlotRenderingInfo;
    import org.jfree.chart.plot.PlotState;
    import org.jfree.chart.plot.ValueMarker;
    import org.jfree.chart.plot.XYPlot;
    import org.jfree.chart.renderer.xy.XYItemRenderer;
    import org.jfree.data.Range;
    import org.jfree.text.TextUtilities;
    import org.jfree.ui.GradientPaintTransformer;
    import org.jfree.ui.Layer;
    import org.jfree.ui.LengthAdjustmentType;
    import org.jfree.ui.RectangleAnchor;
    import org.jfree.ui.RectangleInsets;
    
    public class MyCombinedDomainXYPlot extends CombinedDomainXYPlot {
    
    public MyCombinedDomainXYPlot() {
        super();
        // TODO Auto-generated constructor stub
    }
    
    public MyCombinedDomainXYPlot(ValueAxis domainAxis) {
        super(domainAxis);
        // TODO Auto-generated constructor stub
    }
    
    @Override
    public void draw(Graphics2D g2, Rectangle2D area, Point2D anchor,
            PlotState parentState, PlotRenderingInfo info) {
        super.draw(g2, area, anchor, parentState, info);
        drawDomainMarkers(g2, area, 0, Layer.FOREGROUND);
    }
    
    /**
     * Draws the domain markers (if any) for an axis and layer.  This method is
     * typically called from within the draw() method.
     *
     * @param g2  the graphics device.
     * @param dataArea  the data area.
     * @param index  the renderer index.
     * @param layer  the layer (foreground or background).
     */
    @Override
    protected void drawDomainMarkers(Graphics2D g2, Rectangle2D dataArea,
                                     int index, Layer layer) {
    
        // check that the renderer has a corresponding dataset (it doesn't
        // matter if the dataset is null)
        if (index >= getDatasetCount()) {
            return;
        }
        Collection markers = getDomainMarkers(index, layer);
        ValueAxis axis = getDomainAxisForDataset(index);
        if (markers != null && axis != null) {
            Iterator iterator = markers.iterator();
            while (iterator.hasNext()) {
                Marker marker = (Marker) iterator.next();
                drawDomainMarker(g2, marker, dataArea);
            }
        }
    
    }
    
    
    /**
     * Draws a vertical line on the chart to represent a 'range marker'.
     * 
     * @param g2
     *            the graphics device.
     * @param plot
     *            the plot.
     * @param domainAxis
     *            the domain axis.
     * @param marker
     *            the marker line.
     * @param dataArea
     *            the axis data area.
     */
    public void drawDomainMarker(Graphics2D g2, Marker marker, Rectangle2D dataArea) {
    
            ValueAxis domainAxis = getDomainAxis();
            if (marker instanceof ValueMarker) {
                ValueMarker vm = (ValueMarker) marker;
                double value = vm.getValue();
                Range range = domainAxis.getRange();
                if (!range.contains(value)) {
                    return;
                }
    
                double v = domainAxis.valueToJava2D(value, dataArea,
                        getDomainAxisEdge());
    
                PlotOrientation orientation = getOrientation();
                Line2D line = null;
                if (orientation == PlotOrientation.HORIZONTAL) {
                    line = new Line2D.Double(dataArea.getMinX(), v,
                            dataArea.getMaxX(), v);
                } else if (orientation == PlotOrientation.VERTICAL) {
                    line = new Line2D.Double(v, dataArea.getMinY(), v,
                            dataArea.getMaxY());
                }
    
                final Composite originalComposite = g2.getComposite();
                g2.setComposite(AlphaComposite.getInstance(
                        AlphaComposite.SRC_OVER, marker.getAlpha()));
                g2.setPaint(marker.getPaint());
                g2.setStroke(marker.getStroke());
                g2.draw(line);
    
                String label = marker.getLabel();
                RectangleAnchor anchor = marker.getLabelAnchor();
                if (label != null) {
                    Font labelFont = marker.getLabelFont();
                    g2.setFont(labelFont);
                    g2.setPaint(marker.getLabelPaint());
                    Point2D coordinates = calculateDomainMarkerTextAnchorPoint(
                            g2, orientation, dataArea, line.getBounds2D(),
                            marker.getLabelOffset(),
                            LengthAdjustmentType.EXPAND, anchor);
                    TextUtilities.drawAlignedString(label, g2,
                            (float) coordinates.getX(),
                            (float) coordinates.getY(),
                            marker.getLabelTextAnchor());
                }
                g2.setComposite(originalComposite);
            } else if (marker instanceof IntervalMarker) {
                IntervalMarker im = (IntervalMarker) marker;
                double start = im.getStartValue();
                double end = im.getEndValue();
                Range range = domainAxis.getRange();
                if (!(range.intersects(start, end))) {
                    return;
                }
    
                double start2d = domainAxis.valueToJava2D(start, dataArea,
                        getDomainAxisEdge());
                double end2d = domainAxis.valueToJava2D(end, dataArea,
                        getDomainAxisEdge());
                double low = Math.min(start2d, end2d);
                double high = Math.max(start2d, end2d);
    
                PlotOrientation orientation = getOrientation();
                Rectangle2D rect = null;
                if (orientation == PlotOrientation.HORIZONTAL) {
                    // clip top and bottom bounds to data area
                    low = Math.max(low, dataArea.getMinY());
                    high = Math.min(high, dataArea.getMaxY());
                    rect = new Rectangle2D.Double(dataArea.getMinX(), low,
                            dataArea.getWidth(), high - low);
                } else if (orientation == PlotOrientation.VERTICAL) {
                    // clip left and right bounds to data area
                    low = Math.max(low, dataArea.getMinX());
                    high = Math.min(high, dataArea.getMaxX());
                    rect = new Rectangle2D.Double(low, dataArea.getMinY(), high
                            - low, dataArea.getHeight());
                }
    
                final Composite originalComposite = g2.getComposite();
                g2.setComposite(AlphaComposite.getInstance(
                        AlphaComposite.SRC_OVER, marker.getAlpha()));
                Paint p = marker.getPaint();
                if (p instanceof GradientPaint) {
                    GradientPaint gp = (GradientPaint) p;
                    GradientPaintTransformer t = im
                            .getGradientPaintTransformer();
                    if (t != null) {
                        gp = t.transform(gp, rect);
                    }
                    g2.setPaint(gp);
                } else {
                    g2.setPaint(p);
                }
                g2.fill(rect);
    
                // now draw the outlines, if visible...
                if (im.getOutlinePaint() != null
                        && im.getOutlineStroke() != null) {
                    if (orientation == PlotOrientation.VERTICAL) {
                        Line2D line = new Line2D.Double();
                        double y0 = dataArea.getMinY();
                        double y1 = dataArea.getMaxY();
                        g2.setPaint(im.getOutlinePaint());
                        g2.setStroke(im.getOutlineStroke());
                        if (range.contains(start)) {
                            line.setLine(start2d, y0, start2d, y1);
                            g2.draw(line);
                        }
                        if (range.contains(end)) {
                            line.setLine(end2d, y0, end2d, y1);
                            g2.draw(line);
                        }
                    } else { // PlotOrientation.HORIZONTAL
                        Line2D line = new Line2D.Double();
                        double x0 = dataArea.getMinX();
                        double x1 = dataArea.getMaxX();
                        g2.setPaint(im.getOutlinePaint());
                        g2.setStroke(im.getOutlineStroke());
                        if (range.contains(start)) {
                            line.setLine(x0, start2d, x1, start2d);
                            g2.draw(line);
                        }
                        if (range.contains(end)) {
                            line.setLine(x0, end2d, x1, end2d);
                            g2.draw(line);
                        }
                    }
                }
    
                String label = marker.getLabel();
                RectangleAnchor anchor = marker.getLabelAnchor();
                if (label != null) {
                    Font labelFont = marker.getLabelFont();
                    g2.setFont(labelFont);
                    g2.setPaint(marker.getLabelPaint());
                    Point2D coordinates = calculateDomainMarkerTextAnchorPoint(
                            g2, orientation, dataArea, rect,
                            marker.getLabelOffset(),
                            marker.getLabelOffsetType(), anchor);
                    TextUtilities.drawAlignedString(label, g2,
                            (float) coordinates.getX(),
                            (float) coordinates.getY(),
                            marker.getLabelTextAnchor());
                }
                g2.setComposite(originalComposite);
    
            }
        }
    
    
    
    
    /**
     * Calculates the (x, y) coordinates for drawing a marker label.
     * 
     * @param g2
     *            the graphics device.
     * @param orientation
     *            the plot orientation.
     * @param dataArea
     *            the data area.
     * @param markerArea
     *            the rectangle surrounding the marker area.
     * @param markerOffset
     *            the marker label offset.
     * @param labelOffsetType
     *            the label offset type.
     * @param anchor
     *            the label anchor.
     * 
     * @return The coordinates for drawing the marker label.
     */
    protected Point2D calculateDomainMarkerTextAnchorPoint(Graphics2D g2,
            PlotOrientation orientation, Rectangle2D dataArea,
            Rectangle2D markerArea, RectangleInsets markerOffset,
            LengthAdjustmentType labelOffsetType, RectangleAnchor anchor) {
    
        Rectangle2D anchorRect = null;
        if (orientation == PlotOrientation.HORIZONTAL) {
            anchorRect = markerOffset.createAdjustedRectangle(markerArea,
                    LengthAdjustmentType.CONTRACT, labelOffsetType);
        } else if (orientation == PlotOrientation.VERTICAL) {
            anchorRect = markerOffset.createAdjustedRectangle(markerArea,
                    labelOffsetType, LengthAdjustmentType.CONTRACT);
        }
        return RectangleAnchor.coordinates(anchorRect, anchor);
    
    }
    }
    

提交回复
热议问题