I have updatable OHLCChart.
I need to draw a line over chart.
How to implement it?
If you want to draw a vertical or horizontal line at a given position on an axis, you can use a ValueMarker :
ValueMarker marker = new ValueMarker(position); // position is the value on the axis
marker.setPaint(Color.black);
//marker.setLabel("here"); // see JavaDoc for labels, colors, strokes
XYPlot plot = (XYPlot) chart.getPlot();
plot.addDomainMarker(marker);
Use plot.addRangeMarker() if you want to draw an horizontal line.
Something like this should work if you want to plot a line indicator (like a moving average for example):
XYDataset dataSet = // your line dataset
CombinedDomainXYPlot plot = (CombinedDomainXYPlot) chart.getPlot();
XYPlot plot = (XYPlot) plot.getSubplots().get(0);
int dataSetIndx = plot.getDatasetCount();
plot.setDataset(dataSetIndx, dataSet);
XYLineAndShapeRenderer lineRenderer = new XYLineAndShapeRenderer(true, false);
plot.setRenderer(dataSetIndx, lineRenderer);
Related
I'd like to get stacked area chart with beginning chart in first point and completing in last point like here:
But picture is out of point's range like here:
How can I make stacked area starting exactly from the first point and completing exactly in the last point?
(Different manipulations with dateAxis.setLowerMargin(-0.075D) dateAxis.setUpperMargin(-0.075D) are not helping)
JFreeChart stackedAreaChart = ChartFactory.createStackedAreaChart(name, X_AXIS_TITLE, Y_AXIS_TITLE, dataset,
PlotOrientation.VERTICAL, true, true, false);
CategoryPlot plot = stackedAreaChart.getCategoryPlot();
CategoryAxis dateAxis = plot.getDomainAxis();
dateAxis.setLowerMargin(-0.075D);
dateAxis.setUpperMargin(-0.075D);
dateAxis.setCategoryMargin(0.0D);
StackArea renderer = new StackArea();
dateAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45);
...
plot.setRenderer(renderer);
renderer.setBaseItemLabelGenerator(new LabelGenerator());
renderer.setBaseItemLabelsVisible(true);
...
plot.setRenderer(renderer);
plot.setAxisOffset(new RectangleInsets(5.0, 1.0, 5.0, 1.0));
ValueAxis rangeAxis = plot.getRangeAxis();
NumberAxis axis2 = new NumberAxis(Y_AXIS_TITLE);
axis2.setAutoRangeIncludesZero(false);
axis2.setLabelFont(rangeAxis.getLabelFont());
axis2.setTickLabelFont(rangeAxis.getTickLabelFont());
...
plot.setRangeAxis(1, axis2);
plot.setRangeAxisLocation(1, AxisLocation.TOP_OR_RIGHT);
plot.mapDatasetToRangeAxes(0, Arrays.asList(0, 1));
setAxisColor(rangeAxis, axisColor);
rangeAxis.setTickLabelPaint(ColorUtils.VaadinAWTColor(params.getColorParams().getFontSlideColor()));
rangeAxis.setLabelPaint(ColorUtils.VaadinAWTColor(params.getColorParams().getFontSlideColor()));
You can get the effect you want by using the default margins on the chart's CategoryAxis, i.e. don't change them as the demo does.
CategoryAxis categoryaxis = categoryplot.getDomainAxis();
//categoryaxis.setLowerMargin(0.0D);
//categoryaxis.setUpperMargin(0.0D);
//categoryaxis.setCategoryMargin(0.0D);
I need stacked area to start for the first point—exactly from C1 in your picture, not earlier, and stop on C8, not later.
You may need to adjust the values to get closer to the desired result.
categoryaxis.setLowerMargin(-0.075D);
categoryaxis.setUpperMargin(-0.075D);
categoryaxis.setCategoryMargin(0.0D);
Edited to add working image at end.
I need to add some sort of annotation to a line graph that I've generated. The red line is the data I'm graphing successfully using a XYLineChart and a XYLineAndShapeRenderer. The squares and text are samples of what I would like to add but have been unable to get working. The data for the graph may be updated as fast as once per second.
Here is how I'm creating the chart:
private JFreeChart createChart(XYDataset dataset) {
final JFreeChart result = ChartFactory.createXYLineChart(
TITLE, // chart title
XAXIS, // domain axis label (x-axis)
YAXIS, // range axis label (y-axis)
dataset, // data
PlotOrientation.VERTICAL, // orientation
false, // include legend
true, // tooltips?
false // URLs?
);
customizeChart(result);
return result;
}
private void customizeChart(final JFreeChart result) {
// NOW DO SOME OPTIONAL CUSTOMIZATION OF THE CHART...
// set the background color for the chart...
result.setBackgroundPaint(null); //makes background transparent.
// get a reference to the plot for further customisation...
XYPlot plot = (XYPlot) result.getPlot();
plot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_LEFT);
plot.setRangePannable(false);
XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer(true, true);
// I've also tried to use a spline renderer
// XYSplineRenderer renderer = new XYSplineRenderer();
renderer.setSeriesShapesVisible(0, false);
renderer.setBaseShapesVisible(true);
plot.setRenderer(renderer);
// set the range axis to display integers only...
NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
rangeAxis.setTickUnit(new NumberTickUnit(10.0)); //otherwise tick units will randomly change to be 5's sometimes.
//set the max/min values
rangeAxis.setUpperBound(MAX);
rangeAxis.setLowerBound(MIN);
// rangeAxis.setInverted(true);
rangeAxis.setInverted(false);
//get the other axis for work in the next step.
NumberAxis domainAxis = (NumberAxis) plot.getDomainAxis();
domainAxis.setAutoRange(true);
domainAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
//do some font stuff
Font axisFont = new Font("Tahoma", Font.BOLD, 12);
Font tickFont = new Font("Tahoma", Font.PLAIN, 11);
Font titleFont = new Font("Tahoma", Font.BOLD, 18);
result.getTitle().setFont(titleFont);
rangeAxis.setLabelFont(axisFont);
rangeAxis.setTickLabelFont(tickFont);
domainAxis.setLabelFont(axisFont);
domainAxis.setTickLabelFont(tickFont);
}
Here's how I'm trying to get something to draw right now:
XYPlot plot = chart.getXYPlot();
XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer();
BasicStroke stroke = new BasicStroke(2.0f);
Rectangle2D.Double rect = new Rectangle2D.Double(10, 10, 10, 20);
// renderer.addAnnotation(new XYShapeAnnotation(
// rect, stroke, Color.GREEN), Layer.BACKGROUND);
plot.addAnnotation(new XYShapeAnnotation(
rect, stroke, Color.GREEN));
Ellipse2D.Double circle = new Ellipse2D.Double(8, 8, 20, 20);
renderer.addAnnotation(new XYShapeAnnotation(
circle, stroke, blue), Layer.BACKGROUND);
plot.drawAnnotations((Graphics2D) chartPanel.getGraphics(), chartPanel.getBounds(), chartPanel.getChartRenderingInfo().getPlotInfo());
// This line does draw, but immediately disappears
Graphics2D g2 = (Graphics2D) chartPanel.getGraphics();
Line2D line = new Line2D.Double(0, 100, 500, 350);
g2.draw(line);
Thanks.
Edit with working image:
I think maybe the circle and rectangle I was trying to add are off of the visible chart coordinate space.
It may help to note that org.jfree.chart.annotations typically require that coordinates are specified in model (dataset) coordinates, not view (plot) coordinates.
As I showed in the picture, I want to move the column labels (values 434, 2562, ....) a little upper. Is there any way to configure that?
MY initial problem was that due to the differences between columns, the labels on the last 2 columns are not visible anymore (they are actually 15 and 24 or stg like that). I dont know how to change that.
Thank you
You can use BarRenderer3D.setSeriesPositiveItemLabelPosition.
For example :
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
dataset.addValue(51.0, "Series 1", "key1");
dataset.addValue(44.3, "Series 1", "key2");
// create the chart...
JFreeChart chart = ChartFactory.createBarChart3D("Demo","Category","Value",dataset,PlotOrientation.VERTICAL,false,true,false);
CategoryPlot plot = chart.getCategoryPlot();
CategoryAxis domainAxis = plot.getDomainAxis();
domainAxis.setVisible(false);
NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setUpperMargin(0.15);
BarRenderer3D renderer = (BarRenderer3D) plot.getRenderer();
CategoryItemLabelGenerator generator = new StandardCategoryItemLabelGenerator();
renderer.setSeriesItemLabelGenerator(0, generator);
renderer.setSeriesItemLabelsVisible(0, true);
renderer.setSeriesPositiveItemLabelPosition(0, new ItemLabelPosition(ItemLabelAnchor.OUTSIDE12,TextAnchor.BASELINE_CENTER));
renderer.setItemLabelAnchorOffset(10);
The result is :
CategoryPlot plot = (CategoryPlot) chart.getPlot();
BarRenderer renderer = (BarRenderer) plot.getRenderer();
renderer.setBasePositiveItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.OUTSIDE12, TextAnchor.TOP_CENTER,TextAnchor.HALF_ASCENT_CENTER,0D));
I want to enable display xy coordinates on XYSplineRenderer chart.
NumberAxis numberaxis = new NumberAxis("X");
numberaxis.setAutoRangeIncludesZero(false);
NumberAxis numberaxis1 = new NumberAxis("Y");
numberaxis1.setAutoRangeIncludesZero(false);
XYSplineRenderer xysplinerenderer = new XYSplineRenderer();
XYPlot xyplot = new XYPlot(data1, numberaxis, numberaxis1,
xysplinerenderer);
xyplot.setBackgroundPaint(Color.lightGray);
xyplot.setDomainGridlinePaint(Color.white);
xyplot.setRangeGridlinePaint(Color.white);
xyplot.setAxisOffset(new RectangleInsets(4D, 4D, 4D, 4D));
JFreeChart jfreechart = new JFreeChart("XYSplineRenderer",
JFreeChart.DEFAULT_TITLE_FONT, xyplot, true);
addChart(jfreechart);
You can use a tooltip generator, as shown here, or use a label generator, as shown here. Either one or both can be added to your renderer.
Addendum: As noted in comments, the following code solved the problem:
StandardXYToolTipGenerator ttG =
new StandardXYToolTipGenerator("{1},{2}", format, format);
xysplinerenderer.setBaseToolTipGenerator(ttG);
I want to make the example of jfreechart: XYAreaChartDemo2.java, an xyareachart but the X axis must be of timeSeries. i have tried this:
TimeSeriesCollection dataset1 = new TimeSeriesCollection(timeSeries);//my timeseries
XYSeriesCollection dataset2 = new XYSeriesCollection();
JFreeChart chart = ChartFactory.createXYAreaChart("titulo","Eje x","eje Y", dataset2, PlotOrientation.VERTICAL,true, false,false);
chart.setBackgroundPaint(Color.white);
XYPlot xyplot= chart.getXYPlot();
//fondo
xyplot.setBackgroundPaint(Color.white);
//pone la serie de time en el formato area (pero pierde el formato tiempo)
xyplot.setDataset(dataset1);
but my chart is returned like a areachart with x-axis from 0 to 1.285......
I have a recommended solution here.
Don't limit your mind on making XYAreaChart with TimeSeries X axis. Why not make a TimeSeries chart and render it into XYAreaChart?
Here is how it can be done.
// Create TimeSeriesChart
JFreeChart localJFreeChart = createChart(createDataset());
// Set to be XYAreaChart
XYItemRenderer render = new XYAreaRenderer();
XYPlot plot = localJFreeChart.getXYPlot();
plot.setRenderer(render);
in which
private static JFreeChart createChart(XYDataset paramXYDataset) {
JFreeChart localJFreeChart = ChartFactory.createTimeSeriesChart("Legal & General Unit Trust Prices", "Date", "Price Per Unit", paramXYDataset, true, true, false);
// ...
return (JFreeChart) localJFreeChart;
}
Full code can be seen here.
Most of the code is from TimeSeriesDemo1 in JFreeChart-1.0.14-demo.jar, and modified by myself to meet your requirements.
Hope this could help.
I'm assuming you're using TimeSeries and adding instances of RegularTimePeriod to the data set. By default, the method ChartFactory. createXYAreaChart() uses a NumberAxis for the domain. Instead, use a DateAxis.
XYPlot plot = chart.getXYPlot();
DateAxis domain = new DateAxis("Tiempo");
plot.setDomainAxis(domain);