How to draw line over a JFreeChart chart? - java

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

Change Plot label position in a Combined Plot JFreeChart

Is there a way to change the position of the Category Plot Labels (title) (censored with black bars in the image) to be on top of the chart and / or aligned vertically to each other?
Here's the classes I use to construct it.
var renderer = new LineAndShapeRenderer();
...
var yAxis = new NumberAxis();
...
var xAxis = new CategoryAxis(title);
...
CategoryPlot plot = new CategoryPlot(dataset, xAxis, yAxis, renderer);
...
var combinedPlot = new CombinedRangeCategoryPlot();
combinedPlot.add(plot, weight);
...
I'm using version 1.0.19 of JFreeChart since newer versions produce some visual artifacts.
There has been a misunderstanding: I meant the labels, "Plot 0" and "Plot1", in your example; and I'm asking for the ability to move them on top of the chart…
Invoke setDomainAxisLocation() on each subplot domain axis to move the axis and its label. Alternatively, obtain the required axis references from the List<CategoryPlot> shown below.
plot0.setDomainAxisLocation(AxisLocation.TOP_OR_LEFT);
plot1.setDomainAxisLocation(AxisLocation.TOP_OR_LEFT);
I only need those "Plot 0" and "Plot1" labels on top, not the tick labels…
You can hide the tick labels as desired using setTickLabelsVisible(false), and you can have multiple axes, as shown here.
To adjust the tick label orientation, invoke setCategoryLabelPositions() on each sublot comprising the combined plot. Do this either
When the plot is created.
CategoryAxis axis0 = new CategoryAxis("Plot 0");
axis0.setCategoryLabelPositions(CategoryLabelPositions.UP_90);
CategoryPlot plot0 = new CategoryPlot(…, axis0, …);
…
CategoryAxis axis1 = new CategoryAxis("Plot 1");
axis1.setCategoryLabelPositions(CategoryLabelPositions.UP_90);
CategoryPlot plot1 = new CategoryPlot(…, axis1, …);
After creating the combined plot.
CombinedRangeCategoryPlot combinedplot = new CombinedRangeCategoryPlot(…);
…
List<CategoryPlot> list = combinedplot.getSubplots();
list.get(0).getDomainAxis().setCategoryLabelPositions(CategoryLabelPositions.UP_90);
list.get(1).getDomainAxis().setCategoryLabelPositions(CategoryLabelPositions.UP_90);
Vertical labels are illustrated below.

Unable to hide y axis line in a stacked bar graph

I am trying to hide the y axis line in my stacked bar chart in JFreeChart, and I have already tried below methods:
Setoutlinepaint(null)
Setbackgroundpaint(color.white)
Setoutlinevisible(false)
Categoryaxis.setaxislinevisible(false)
Categoryaxis.setvisible(false)
Many thanks in advance for your help.
Invoking the parent method setAxisLineVisible() appears to produce the expected result for either a CategoryAxis or a ValueAxis. Starting from this example, the following changes in createChart() produce the result shown. I've changed the plot orientation to make the domain axis vertical, and I've invoked setAxisLineVisible(false) on both axes.
CategoryPlot plot = (CategoryPlot) chart.getPlot();
plot.setOrientation(PlotOrientation.HORIZONTAL);
CategoryAxis domainAxis = plot.getDomainAxis();
domainAxis.setAxisLineVisible(false);
plot.setDomainAxis(domainAxis);
NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setAxisLineVisible(false);
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
Axis lines not visible:
Axis lines visible:
Note that the factory methods for both bar chart stacked bar chart use the same axes.

JFREECHART line chart : Want X axis to be collection of date ranges

I am new to JFreeChart. My requirement is to display the X axis (time-axis) as following (time ranges will be configurable as per user input) for a line chart with suppose 3 variables:
3rdAug-8thAug..10thAug-15thAug.. [ and so on ]
Currently my graph's X axis is like this :
1..2..3..4..5 ..
[Unable to attach screenshots]
My demo code is as follows :
private JFreeChart createChart(final XYDataset dataset) {
// create the chart...
final JFreeChart chart = ChartFactory.createXYLineChart(
"Line Chart Demo ", // chart title
"X", // x axis label
"Y", // y axis label
dataset, // data
PlotOrientation.VERTICAL,
true, // include legend
true, // tooltips
false // urls
);
// OPTIONAL CUSTOMISATION OF THE CHART...
chart.setBackgroundPaint(Color.white);
// get a reference to the plot for further customisation...
final XYPlot plot = chart.getXYPlot();
plot.setBackgroundPaint(Color.white);
plot.setDomainGridlinePaint(Color.white);
plot.setRangeGridlinePaint(Color.white);
final XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
renderer.setSeriesLinesVisible(0, true); //for line visibility
renderer.setSeriesShapesVisible(1, false);
plot.setRenderer(renderer);
// change the auto tick unit selection to integer units only...
final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
// final Axis range = plot.get
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
// OPTIONAL CUSTOMISATION COMPLETED.
return chart;
}
Can anyone point me in the right direction here?
How do I get only the required values shown on the X axis?
XYPlot differ between domain axes and range axes. In your case the X axis is the domain axis whereas the Y axis is the range axis.
Valuexis domainAxis = plot.getDomainAxis();
You can also set a different domain axis:
ValueAxis dAxis = new ...
plot.setDomainAxis(dAxis);
You want to use JFreeChart's TimeLine interface to limit the shown dates on the DateAxis (which is actually the domain-axis in your case, as already pointed out by #Uli). For your requirement the default implementation SegmentedTimeline should fulfill your requirements. Just configure it and pass it on to your axis:
SegmentedTimeline timeline = new SegmentedTimeline(
86400000l, // segment size = one day in ms (24*3600*1000)
5, // include 5 segments (days)
2); // exclude 2 segments (days)
DateAxis axis = new DateAxis();
axis.setTimeline(timeline);
And don't forget to configure the plot to use the new DateAxis, as XYPlot uses NumberAxis by default:
plot.setDomainAxis(axis);
hth,
- martin

JFreeChart align BarChart width across subplots

I'm building multiple stacked bar charts (subplots) that are combined through a CombinedRangeCategoryPlot.
As the subplots datasets do not have the same number of items and since JFreeChart decides to allocate the same space for each subplot, I have different widths of bars.
Is there any way I can align their width (even if it means that the subplots have different widths)?
Please see below for the result and the code I have so far.
Many thanks,
Thomas
//Builds commong range axis
NumberAxis rangeAxis = new NumberAxis("%");
rangeAxis.setRange(0, 1.0);
rangeAxis.setNumberFormatOverride(NumberFormat.getPercentInstance());
//Builds common data set
CombinedRangeCategoryPlot combinedPlots = new CombinedRangeCategoryPlot(rangeAxis);
for (int groupIndex=0; groupIndex<LeakGroups.values().length; ++groupIndex){
//Builds category axis
CategoryAxis categoryAxis = new CategoryAxis(GuiConstants.LEAK_GROUPS_LABELS[groupIndex]);
//Sets margins between bars
categoryAxis.setCategoryMargin(0.5f);
//Builds bar renderer
StackedBarRenderer barRenderer = new StackedBarRenderer();
barRenderer.setRenderAsPercentages(true);
//Builds dot/level renderer
LineAndShapeRenderer dotRenderer = new LineAndShapeRenderer();
//dotRenderer.setSeriesLinesVisible(0, false);
//dotRenderer.setSeriesShapesVisible(0, false);
//dotRenderer.setSeriesLinesVisible(1, false);
//Defines level shape height (depends on chart size): nominal values are for a height of 1000px
int shapeHeightPx = (int) Math.round(20 * (this.getHeight() / 1000.0));
dotRenderer.setSeriesShape(1, new Rectangle(-1, -shapeHeightPx/2, 2, shapeHeightPx));
//Builds plot
CategoryPlot plot = new CategoryPlot();
plot.setDomainAxis(categoryAxis);
plot.setDataset(0, data[groupIndex].bars);
plot.setRenderer(0, barRenderer);
plot.setDataset(1, data[groupIndex].dots);
plot.setRenderer(1, dotRenderer);
//Adds to combined
combinedPlots.add(plot);
}
combinedPlots.setOrientation(PlotOrientation.HORIZONTAL);
//Puts range axis at the bottom
combinedPlots.setRangeAxisLocation(AxisLocation.BOTTOM_OR_RIGHT);
//Changes plot render sequence so that bars are in the background and shapes in front
combinedPlots.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);
//Shows gridlines for categories and not for values
combinedPlots.setDomainGridlinesVisible(true);
combinedPlots.setRangeGridlinesVisible(false);
//Creates chart
JFreeChart chart = new JFreeChart("Leaks", combinedPlots);
//Sets a margin right to allow space for last catergory label ("100%")
chart.setPadding(new RectangleInsets(0, 0, 0, 20));
return chart;
For some reason, the weight gets reset to value 1 when adding the plot.
By way of explanation,
The add(CategoryPlot subplot) method specifies a default weight of 1,
The add(CategoryPlot subplot, int weight) method lets you specify a weight value.
After a few hours of search, found the solution: use plot.setWeight().
For some reason, the weight gets reset to value 1 when adding the plot to the CombinedRangeCategoryPlot, hence it has to be set after.
Hope this helps.

Plot with gridline on top of XYDifferenceRenderer

I'm making (time series) moutain chart using JFreeChart. So, i made 2 timeseries - the data one and the one with all range values are zero.
TimeSeriesCollection dataset2 = new TimeSeriesCollection();
dataset2.addSeries(close); //my data series/
dataset2.addSeries(zeroseries); /zero series/
Then, i used XYDifferenceRenderer to fill the gap between 2 series with my desired color.
Code to create the chart and set renderer :
final JFreeChart chart = garch_differencechart(url);//my method to create the chart//
final ChartPanel chartPanel = new ChartPanel(chart);
final XYPlot plot = (XYPlot) chart.getPlot();
chart.setBackgroundPaint(Color.WHITE);
plot.setBackgroundPaint(Color.WHITE);
XYDifferenceRenderer renderer = new XYDifferenceRenderer();
renderer.setPositivePaint(new Color(202, 225, 255));
renderer.setSeriesPaint(0, new Color(72, 118, 255));
renderer.setSeriesStroke(0, new BasicStroke(1.2f));
plot.setRenderer(renderer);
Code to set GridLines visible :
plot.setDomainGridlinesVisible(true);
plot.setDomainGridlinePaint(new Color(234,234,234));
plot.setDomainGridlineStroke(new BasicStroke(0.5f));
plot.setRangeGridlinesVisible(true);
plot.setRangeGridlinePaint(new Color(234,234,234));
plot.setRangeGridlineStroke(new BasicStroke(0.5f));
However, the renderer covered the plot's gridline (it seems that the gridline was painted before the XYDifferenceRenderer).
How could I get the plot with gridline on top of XYDifferenceRenderer?
The gridlines show though in the demos and API. An sscce would be dispositive, but I suspect your grid and fill paints just need more contrast.

Categories

Resources