2012-10-16 2 views
1

CombinedDomainXYPlot에 마커를 표시하고 싶습니다. 이것은 작동하지 않습니다. 각 하위 플롯에 대해 표식을 추가 할 수 있습니다. 하지만 CombinedDomainXYPlot에 추가하고 싶습니다. 이 문제에 관해 나에게 뭔가를 말할 수있는 사람. 나는 십자형으로 행동이 동일하다고 생각합니다.CombinedDomainXYPlot에서 마커/십자형 커서 만들기

이것은 CombinedDomainXYPlot을 만들고 마커를 추가하는 예제입니다. 추가 마커는 createCombinedChart()

import java.awt.Font; 

import javax.swing.JPanel; 

import org.jfree.chart.ChartPanel; 
import org.jfree.chart.ChartUtilities; 
import org.jfree.chart.JFreeChart; 
import org.jfree.chart.annotations.XYTextAnnotation; 
import org.jfree.chart.axis.AxisLocation; 
import org.jfree.chart.axis.NumberAxis; 
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.XYPlot; 
import org.jfree.chart.renderer.xy.StandardXYItemRenderer; 
import org.jfree.chart.renderer.xy.XYItemRenderer; 
import org.jfree.data.xy.XYDataset; 
import org.jfree.data.xy.XYSeries; 
import org.jfree.data.xy.XYSeriesCollection; 
import org.jfree.ui.ApplicationFrame; 
import org.jfree.ui.RefineryUtilities; 

/** 
* A demonstration application showing how to create a combined chart. 
*/ 
public class MarkerDemo2 extends ApplicationFrame { 

/** 
* Constructs a new demonstration application. 
* 
* @param title the frame title. 
*/ 
public MarkerDemo2(String title) { 

    super(title); 
    JFreeChart chart = createCombinedChart(); 
    ChartPanel panel = (ChartPanel) createDemoPanel(); 
    panel.setPreferredSize(new java.awt.Dimension(500, 270)); 
    setContentPane(panel); 

} 

/** 
* Creates a combined chart. 
* 
* @return The combined chart. 
*/ 
private static JFreeChart createCombinedChart() { 

    // create subplot 1... 
    XYDataset data1 = createDataset1(); 
    XYItemRenderer renderer1 = new StandardXYItemRenderer(); 
    NumberAxis rangeAxis1 = new NumberAxis("Range 1"); 
    XYPlot subplot1 = new XYPlot(data1, null, rangeAxis1, renderer1); 
    subplot1.setRangeAxisLocation(AxisLocation.BOTTOM_OR_LEFT); 

    // add secondary axis 
    subplot1.setDataset(1, createDataset2()); 
    NumberAxis axis2 = new NumberAxis("Range Axis 2"); 
    axis2.setAutoRangeIncludesZero(false); 
    subplot1.setRangeAxis(1, axis2); 
    subplot1.setRangeAxisLocation(1, AxisLocation.BOTTOM_OR_RIGHT); 
    subplot1.setRenderer(1, new StandardXYItemRenderer()); 
    subplot1.mapDatasetToRangeAxis(1, 1); 

    XYTextAnnotation annotation = new XYTextAnnotation("Hello!", 50.0, 10000.0); 
    annotation.setFont(new Font("SansSerif", Font.PLAIN, 9)); 
    annotation.setRotationAngle(Math.PI/4.0); 
    subplot1.addAnnotation(annotation); 

    // create subplot 2... 
    XYDataset data2 = createDataset2(); 
    XYItemRenderer renderer2 = new StandardXYItemRenderer(); 
    NumberAxis rangeAxis2 = new NumberAxis("Range 2"); 
    rangeAxis2.setAutoRangeIncludesZero(false); 
    XYPlot subplot2 = new XYPlot(data2, null, rangeAxis2, renderer2); 
    subplot2.setRangeAxisLocation(AxisLocation.TOP_OR_LEFT); 

    // parent plot... 
    CombinedDomainXYPlot plot = new CombinedDomainXYPlot(new NumberAxis("Domain")); 
    plot.setGap(10.0); 

    // add the subplots... 
    plot.add(subplot1, 1); 
    plot.add(subplot2, 1); 
    plot.setOrientation(PlotOrientation.VERTICAL); 

    // Add marker 
    Marker marker = new IntervalMarker(30, 40); 
    plot.addDomainMarker(marker); 
    // Working 
    // subplot1.addDomainMarker(marker); 

    // return a new chart containing the overlaid plot... 
    JFreeChart chart = new JFreeChart("CombinedDomainXYPlot Demo", 
      JFreeChart.DEFAULT_TITLE_FONT, plot, true); 
    ChartUtilities.applyCurrentTheme(chart); 
    return chart; 

} 

/** 
* Creates a sample dataset. 
* 
* @return Series 1. 
*/ 
private static XYDataset createDataset1() { 

    // create dataset 1... 
    XYSeries series1 = new XYSeries("Series 1a"); 
    series1.add(10.0, 12353.3); 
    series1.add(20.0, 13734.4); 
    series1.add(30.0, 14525.3); 
    series1.add(40.0, 13984.3); 
    series1.add(50.0, 12999.4); 
    series1.add(60.0, 14274.3); 
    series1.add(70.0, 15943.5); 
    series1.add(80.0, 14845.3); 
    series1.add(90.0, 14645.4); 
    series1.add(100.0, 16234.6); 
    series1.add(110.0, 17232.3); 
    series1.add(120.0, 14232.2); 
    series1.add(130.0, 13102.2); 
    series1.add(140.0, 14230.2); 
    series1.add(150.0, 11235.2); 

    XYSeries series1b = new XYSeries("Series 1b"); 
    series1b.add(10.0, 15000.3); 
    series1b.add(20.0, 11000.4); 
    series1b.add(30.0, 17000.3); 
    series1b.add(40.0, 15000.3); 
    series1b.add(50.0, 14000.4); 
    series1b.add(60.0, 12000.3); 
    series1b.add(70.0, 11000.5); 
    series1b.add(80.0, 12000.3); 
    series1b.add(90.0, 13000.4); 
    series1b.add(100.0, 12000.6); 
    series1b.add(110.0, 13000.3); 
    series1b.add(120.0, 17000.2); 
    series1b.add(130.0, 18000.2); 
    series1b.add(140.0, 16000.2); 
    series1b.add(150.0, 17000.2); 

    XYSeriesCollection collection = new XYSeriesCollection(); 
    collection.addSeries(series1); 
    collection.addSeries(series1b); 
    return collection; 

} 

/** 
* Creates a sample dataset. 
* 
* @return A sample dataset. 
*/ 
private static XYDataset createDataset2() { 

    // create dataset 2... 
    XYSeries series2 = new XYSeries("Series 2"); 

    series2.add(10.0, 6853.2); 
    series2.add(20.0, 9642.3); 
    series2.add(30.0, 8253.5); 
    series2.add(40.0, 5352.3); 
    series2.add(50.0, 3532.0); 
    series2.add(60.0, 2635.3); 
    series2.add(70.0, 3998.2); 
    series2.add(80.0, 1943.2); 
    series2.add(90.0, 6943.9); 
    series2.add(100.0, 7843.2); 
    series2.add(105.0, 6495.3); 
    series2.add(110.0, 7943.6); 
    series2.add(115.0, 8500.7); 
    series2.add(120.0, 9595.9); 

    return new XYSeriesCollection(series2); 

} 

/** 
* Creates a panel for the demo (used by SuperDemo.java). 
* 
* @return A panel. 
*/ 
public static JPanel createDemoPanel() { 
    JFreeChart chart = createCombinedChart(); 
    ChartPanel panel = new ChartPanel(chart); 
    panel.setMouseWheelEnabled(true); 
    return new ChartPanel(chart); 
} 

/** 
* Starting point for the demonstration application. 
* 
* @param args ignored. 
*/ 
public static void main(String[] args) { 

    MarkerDemo2 demo = new MarkerDemo2(
      "JFreeChart: CombinedDomainXYPlotDemo4.java"); 
    demo.pack(); 
    RefineryUtilities.centerFrameOnScreen(demo); 
    demo.setVisible(true); 

} 

} 
+0

어노테이션이 결합 된 플롯에 나타나는 것을 어떻게 예상 했습니까? – GrahamA

+0

왜 그럴까요? 주석을 추가하는 방법은 있지만 거기에 반응을 일으키지 않는 것 같습니다. – hami

+0

왜 그렇지 않은가요? 예를 들어 주석을 두 플롯에 모두 표시하겠습니까? 나는 왜 그들이 아래에서 일하지 않는지 설명했지만 더 이상의 정보 없이는 해결책을 제안 할 수 없다. – GrahamA

답변

2

그레이엄 덕분에 나에게 맞는 CombinedDomainXYPlot의 조정 버전을 개발했습니다. 결과는 다음과 같습니다.

CombinedDomainXYPlot with Marker

나는 이것을 달성하기 위해 XYPlot 및 XYLineAndShapeRenderer에서 코드를 합병했다. 다음은 소스 코드입니다.

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); 

} 
} 
2

drawAnnotations은 불행하게도, XYPlotCombinedDomainXYPlot 서브 클래스 XYPlot을 구현하지만 draw 자사의 오버라이드 (override) 구현에 drawAnnotations 전화 또는 줄거리에에 주석을 전달하지 않습니다이다.

addAnnotationremoveAnnotation의 구현에 CombinedDomainXYPlot을 서브 클래 싱하여 제공 할 수 있습니다.