I'm having an issue with a JFreeChart overlaid graph. I'm using JFreeChart 1.0.13. What I am trying to do seems like it was easier to do in earlier versions of JFreeChart?
The graph shows a line chart and a bar chart. The data range plotted by the line chart for the Y axis is in the 0-100 range, and the axis for the bar chart is in the 0-5 range.
Individually, when I lay out each chart and paint it, they look great. Here's an example:
Bar Chart
Line Chart
But when I overlay them, the bar chart gets scaled down to look incredibly useless... presumably because the scales of the two datasets are so different.
Example:
What I really want is to split the series data for the two datasets, and display the 0-100 range for the line chart on the left hand Y axis and to have the bar chart displayed full size as in my first example below, but have the scale 0-5 displayed on the right hand Y axis side of the graph.
To create the graph, I am first creating the bar chart using an XYSeriesCollection, adding the data and creating the plot...
XYSeriesCollection histogramDataset= new XYSeriesCollection();
XYSeries xy= new XYSeries("Temp");
xy.add(100,0.0);
xy.add(101,0.3769791404875597);
histogramDataset.addSeries(xy);
...
final NumberAxis xAxis = new NumberAxis("Temperature C");
xAxis.setAutoRangeIncludesZero(false);
final ValueAxis yAxis = new NumberAxis("Percent Time above Temperature");
final XYItemRenderer renderer = new XYBarRenderer();
final XYPlot plot = new XYPlot((XYDataset) histogramDataset, xAxis, yAxis, renderer);
Then I create the line chart in a similar way and add the second series to the plot...
final XYSeries xy = new XYSeries("First");
final XYDataset xySeriesData = new XYSeriesCollection();
final XYItemRenderer xyLineRenderer = new XYLineAndShapeRenderer();
xyLineRenderer.setSeriesShape(0, new Line2D.Double(0.0, 0.0, 0.0, 0.0));
xyLineRenderer.setSeriesStroke(0, new BasicStroke(4.5f));
xy.add(100,100.0);
xy.add(101,100.0);
xyseriesData.add(xy);
plot.setDataset(1, xySeriesData);
plot.setRenderer(1, xyLineRenderer);
plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);
My suspicion is that somehow each graph needs to be it's own plot and combined together. Can anyone help? What I am going for here is something like this:
Except I don't want the bar chart to be a background image. The X axis should be the same, and the Y axis should be on the right hand side with the proper scale that allows the graph to be shown full size.
Any/all replies are appreciated...
I see you're adding a second data set and renderer to your plot, but you're forcing them to use the same range axis. Instead, give the plot a new NumberAxis for the range of the second data set.
As an aside, don't overlook the axis related example in the JFreeChart Demo, and don't underestimate the value of the JFreeChart Developer Guide.
Related
I am using Jaspersoft Studio to create the report file with charts.
When I use the bar chart and try to display the bar values labels these are covered by the margins. In my opinion this looks like a bug, is there any way to show the labels properly?
To better illustrate the problem you can see the issue on the picture and also find in red the expected values.
EDIT
Here is my progress customizing the bar chat. So far I could make several changes but I am stuck with the most important one.
I tried using huge values for the margins without any visual effect.
rangeAxis.setUpperMargin(200);
rangeAxis.setLowerMargin(200);
I also played with the bounds. In that case I can see the entire labels but the problem is that the values won't stop at 100 (so that is not a valid solution).
I discovered the reason why the margins are completely ignored:
public void setUpperMargin(double margin)
Sets the upper margin for the axis (as a percentage of the axis range) and sends an AxisChangeEvent to all registered listeners. This margin is added only when the axis range is auto-calculated - if you set the axis range manually, the margin is ignored.
But if I remove the margins then the bounds are autocalculated from 0-125 what is not the scope.
As usual, any suggestion will be welcome.
For a better understanding you can download the sample code from my GitHub repository.
GitHub: https://github.com/MichaelKnight/jaspertest.git
The chart in jasper report is generated by the jfreechart library. In your case you can:
1) Set the range axis upper margin to give more space to value label (see jfreechart BarChartDemo5).
2) Draw the label inside the bar (see jfreechart BarChartDemo7) After edit if you need fixed upper value of axis you need to use this, hence the label has no space left if upper limit equals max bar value
To customize your bar chart in jasper report create a customizer class (MyChartCustomizer) extending the JRChartCustomizer. This will expose:
public void customize(JFreeChart chart, ChartComponent chartComponent)
{
//Simple example of increasing upper margin on range axis, to print label
//inside of bar see jfreechart BarChartDemo7
CategoryPlot plot = (CategoryPlot) chart.getPlot();
NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setUpperMargin(0.20); //Increase or decrease to change upper margin in percentages (0 --> 1.0)
rangeAxis.setAutoRange(true); //make sure that fixed range is not set
}
add the class to classpath and in jrxml set the customizerClass attribute
<barChart>
<chart customizerClass="my.package.MyChartCustomizer">
....
</chart>
...
</barChart>
I am using the plotyy function to produce the chart in the image below.
I have two issues with this chart. First issue being having two x-axes I want the zero on the left hand side of my chart to be level with the zero on the right hand side. Is there anyway I can make this happen?
Lastly I want to put some labels on the x-axis however you can that I labels have numbers on top of them. I only want the labels to be visible which I cannot seem to do?
Below is my code.
x_labels = data_cell(2:end, 1);
risk_tot = cell2mat(data_cell(2:end, 2));
risk_cont = cell2mat(data_cell(2:end, 3));
[pp,h1,h2]=plotyy((1:length(risk_tot)),risk_tot,(1:length(risk_tot)),risk_cont,'bar','stem');
set(gca,'XtickL',x_labels);
set(h1,'FaceColor',my_Blue2(40,:),'EdgeColor',my_Blue2(40,:))
set(h2,'Color',my_Orange(1,:),'LineWidth',0.5,'MarkerEdgeColor',my_Orange(1,:))
set(pp(1),'Box','off')
set(pp(2),'Box','off')
Update
I have managed to resolve the second issue with the x-axis labels. I simply added the line below. This sets the second x-axis labels to empty.
Still can't fix the first issue.
set(pp(2),'XTickLabel',[]);
Try linkaxes:
linkaxes(pp,'y')
You may need to adjust the axes limits with pp(1).Ylim = ... to get the desired result.
I have a software that displays charts using Visiblox.
The user can change the style of any of the axes from linear to logarithmic. And I have a small problem:
When zoomed the linear chart will display grid lines on the graph and values on the axis, as can be seen in the following two pictures:
The problem is that when switched to logarithmic mode the chart no linger displays the reference numbers or grid lines when zoomed:
So our users are now complaining they have no reference to analyze the curves.
We don't do any special configuration to linear axes opposed to log ones here's the code:
for linear axes:
this.CalibrationChartXAxis = new LinearAxis();
this.CalibrationChartYAxis = new LinearAxis();
for log axes:
this.CalibrationChartXAxis = new LogarithmicAxis();
this.CalibrationChartYAxis = new LogarithmicAxis();
adding the ranges:
this.CalibrationChartXAxis.Range = new DoubleRange(minX, maxX);
this.CalibrationChartYAxis.Range = new DoubleRange(minY, maxY);
and of course binding them to the view:
<Grid Grid.Row="0" Grid.RowSpan="2" Grid.ColumnSpan="2">
<charts:Chart x:Name="PlotChart" Behaviour="{Binding Path=CalibrationCurveChartViewModel.PlotChartBehavior}"
XAxis="{Binding Path=CalibrationCurveChartViewModel.CalibrationChartXAxis}"
YAxis="{Binding Path=CalibrationCurveChartViewModel.CalibrationChartYAxis}"
Background="Transparent" LegendVisibility="Collapsed" Margin="0" BorderBrush="Blue" BorderThickness="1">
<charts:Chart.Series>
...
</charts:Chart.Series>
</charts:Chart>
</Grid>
I have no idea why the two axes types behave differently.
I've tried turning AutoScaleToVisibleData on and off, or setting ShowMinorTicks, but that seems to do nothing.
I'm at a loss about what to do.
Can anyone help?
I ran into something similar before. Not sure if this is related, but you can check out this post for a possible workaround.
Logarithmic Axis on Visiblox
in my project i have used achartengine for Scatter Charts but i am not able to click on point, so now i want use Scatter Charts of AndroidPlot, how can we implement that Scatter charts of AndroidPlot library ?
i have used below but i am not getting sample of Scatter Chart sample.
http://androidplot.com/
http://homepages.ius.edu/RWISMAN/C490/html/Android-Plot.htm
Thanks
A scatter chart is basically just an XY Chart where the points are not connected by lines. AndroidPlot uses formatters to store information about how a series should be displayed. In this case you'd use a LineAndPointFormatter that doesnt draw the line segments. For example here's how you would instantiate one that only draws red dots:
// passing null as the line color disables lines
LineAndPointFormatter lpf = new LineAndPointFormatter(null, Color.RED, null, null)
I am creating a Chart (DataVisualization.Charting.Chart) programmatically, which is a Stacked Bar chart.
I am also adding Legend entries programmatically to it. I want to show the Legend at the bottom of the chart.
But, while doing so, the Legend overlapps with the X-axis of the chart.
Here is the code I am using:
Private Function GetLegend(ByVal legendName As String, ByVal s As Single) As System.Windows.Forms.DataVisualization.Charting.Legend
Dim objLegend As System.Windows.Forms.DataVisualization.Charting.Legend = New System.Windows.Forms.DataVisualization.Charting.Legend()
objLegend.Name = legendName
objLegend.Font = New System.Drawing.Font("Verdana", s)
objLegend.IsDockedInsideChartArea = False
objLegend.Docking = Docking.Bottom
Return objLegend
End Function
Below statement adds that Legend to the chart
_msChart.Legends.Add(GetLegend("SomeValue1", 10.0F))
Any idea, what is missing? I want to show the legend at the bottom only, but it should not overlapp with the X-axis.
I had the same problem today. Try adding:
objLegend.Position.Auto = true
objLegend.DockedToChartArea = "yourChartAreaName"
That did not help me but I found on the net that this might be helpful (and clean solution).
What actually worked for me was moving chart area to make space for legend so it no longer overlaps. My legend was on top so this code worked for me:
chart.ChartAreas[0].Position.Y = 15
You can try resizing it instead, forcing it to be for example 20 pixels shorter than chart.Size.
Hope this helps.
I had an overlapping legend/chart area problem as well but none of the other suggestions here seemed to make any difference. I think the problem stems from legend text wrapping to two lines and the sizing algorithms not taking account of this.
The ideas here got me thinking more clearly about the problem though, and I was able control the size and position of the chart area using the following.
Chart1.ChartAreas[0].InnerPlotPosition = new ElementPosition(15, 5, 90, 75);
There's not much intellisense on those parameters, but as well as I could deduce, the parameters are all percentages of the total chart area (I initially thought they might be pixel values and got some very odd results). So what I've written above would set the plot area to start at 15% in from the left edge of the chart image and 5% down from the top, and have a width of 90% and a height of 75%.