我想在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 :(得分:2)
drawAnnotations
已在XYPlot
中实施,遗憾的是CombinedDomainXYPlot
子类XYPlot
,但未在其drawAnnotations
的已覆盖实施中调用draw
或将注释转发到子图。
您可以通过继承addAnnotation
来提供removeAnnotation
和CombinedDomainXYPlot
的实施。
答案 1 :(得分:2)
感谢格雷厄姆,我开发了一个调整版的CombinedDomainXYPlot,这对我有用。结果看起来像这样。
我合并了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);
}
}