After creating a line chart by passing to JFreeChart constructor a XYSeriesCollection dataset, I'm trying to get either series Stroke/Paint/Shape as:
XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer)chart.getXYPlot().getRenderer();
for (int i = 0; i < dataset.getSeriesCount(); i++) {
renderer.getSeriesStroke(i);
renderer.getSeriesPaint(i);
renderer.getSeriesShape(i);
}
but all return null.
Why is that? How can I get the non-null objects?
An XYLineAndShapeRenderer is an XYItemRenderer, which supports "rendering the visual representation of a single (x, y) item on an XYPlot." Although the corresponding series properties are null, the item properties are accessible. Starting from this example, The following changes produce the output shown:
Code:
XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer)chart.getXYPlot().getRenderer();
for (int i = 0; i < xyPlot.getDataset().getSeriesCount(); i++) {
System.out.println(renderer.getItemStroke(i, 0));
System.out.println(renderer.getItemPaint(i, 0));
System.out.println(renderer.getItemShape(i, 0));
System.out.println(renderer.getItemShape(i, N));
}
Console:
$ java -cp .:$JFREE_LIB/* ScatterShape
java.awt.BasicStroke#d1a007c0
java.awt.Color[r=255,g=85,b=85]
java.awt.geom.Rectangle2D$Double[x=-3.0,y=-3.0,w=6.0,h=6.0]
java.awt.geom.GeneralPath#7ef51f0f
Related
I have tried the following with the default renderer
CategorySeries series = new CategorySeries("First test");
int numSlide = portions.length;
for (int i = 0; i < numSlide; i++){
series.add(seriesNames[i]+" ("+portions[i]+" %)", portions[i]);
}
DefaultRenderer defaultRenderer = new DefaultRenderer();
SimpleSeriesRenderer simpleSeriesRenderer = null;
for (int i = 0; i < numSlide; i++){
simpleSeriesRenderer = new SimpleSeriesRenderer();
simpleSeriesRenderer.setColor(colors[i]);
simpleSeriesRenderer.setChartValuesFormat(new DecimalFormat("###,###,##0.0"));
defaultRenderer.addSeriesRenderer(simpleSeriesRenderer);
}
defaultRenderer.setInScroll(true);
defaultRenderer.setZoomButtonsVisible(false);
defaultRenderer.setZoomEnabled(true);
defaultRenderer.setLabelsTextSize(18); //value size
defaultRenderer.setLabelsColor(R.color.primary_dark);
defaultRenderer.setShowLegend(false);
defaultRenderer.setClickEnabled(true);
defaultRenderer.setPanEnabled(true);
defaultRenderer.setShowLabels(true);
defaultRenderer.setShowLegend(true);
//return the pie chart view
return ChartFactory.getPieChartView(context, series, defaultRenderer);
Now the above produces
What am looking forward to get is to have the percentage values eg: 2% inside the chart area something which looks like this
How do i get the percentage values to be displayed inside the charts?
You want to display values and hide labels. Do that like so in your renderer:
defaultRenderer.setShowLabels(false);
defaultRenderer.setDisplayValues(true);
Also, your series names should probably not contain the values, so change the following line
series.add(seriesNames[i]+" ("+portions[i]+" %)", portions[i]);
to
series.add(seriesNames[i], portions[i]);
I'm using JFreeChart to graph some data, and I've set it up so that the graph shows my standard error for each point as such:
The label shows the Y value for each point, but I'd like to be able to show the Y value for the standard errors as well. Furthermore, is there a way to make it so this data only shows up if hovered over with the mouse?
This is the code I use to add both the error and the labels:
XYErrorRenderer renderer = new XYErrorRenderer();
renderer.setBaseLinesVisible(true);
renderer.setBaseShapesVisible(true);
renderer.setBaseItemLabelGenerator(new StandardXYItemLabelGenerator("{2}",
NumberFormat.getNumberInstance(),NumberFormat.getNumberInstance()));
renderer.setBaseItemLabelsVisible(true);
chart.getXYPlot().setRenderer(renderer);
Thanks in advance.
XYErrorRenderer inherits its implementation of drawItemLabel() from the abstract parent, which knows nothing about the error bars. You'll need to override drawItem() in a custom renderer subclass to draw the extra labels. The source for drawItemLabel() may serve as a guide.
Addendum: A less ambitious alternative would be to display the error range in a tooltip. The custom StandardXYToolTipGenerator below specifies a custom format string and overrides createItemArray() to supply the relevant y values from the dataset. As your XYDataset is a YIntervalSeriesCollection, you can cast it as shown below.
renderer.setBaseToolTipGenerator(new StandardXYToolTipGenerator(
"{0}: {1}…{2}", NumberFormat.getInstance(), NumberFormat.getInstance()) {
#Override
protected Object[] createItemArray(XYDataset data, int series, int item) {
YIntervalSeriesCollection d = (YIntervalSeriesCollection) data;
Object[] result = new Object[3];
double y = d.getYValue(series, item);
result[0] = getYFormat().format(y);
double min = d.getStartYValue(series, item);
result[1] = getYFormat().format(min);
double max = d.getEndYValue(series, item);
result[2] = getYFormat().format(max);
return result;
}
});
I am working on graph chart using aChartEngine, the problem faced is that the although graph are generating, problem is graph is not coming as per need inside the view, how to fix it ??
When selecting Bar from drop down
After Zooming Out and panning(by interacting with graph)
Here is my code
private static XYMultipleSeriesDataset getBarDataset(int rightAnswers, int wrongAnswers)
{
String[] labels={"right","wrong"};
List<Double> values = new ArrayList<Double>();
values.add((double) rightAnswers);
values.add((double) wrongAnswers);
XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
for (int i = 0; i < titles.length; i++)
{
XYSeries series = new XYSeries(titles[i]);
series.add(i,values.get(i));
dataset.addSeries(i,series);
}
return dataset;
}
2)Renderer
protected static XYMultipleSeriesRenderer buildBarRenderer(int[] colors) {
XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
renderer.addXTextLabel(0, "right");
renderer.addXTextLabel(1, "wrong");
renderer.setChartTitle("Results");
int length = colors.length;
SimpleSeriesRenderer r = new SimpleSeriesRenderer();
r.setColor(colors[0]);
renderer.addSeriesRenderer(r);
r = new SimpleSeriesRenderer();
r.setColor(colors[1]);
renderer.addSeriesRenderer(r);
renderer.setScale(10);
renderer.setXLabels(0);
renderer.setApplyBackgroundColor(true);
renderer.setBackgroundColor(Color.WHITE);
renderer.setAxesColor(Color.CYAN);
renderer.setBarWidth(30);
return renderer;
}
3) the view
ChartFactory.getBarChartView(context, getBarDataset(rightAnswers, wrongAnswers), buildBarRenderer(new int[]{Color.GREEN,Color.RED}), Type.DEFAULT);
Query
1) How to fix the position and exact panned graph
2) Can we have 3d effect on bars??How??
3) Is there any other library simpler compared to aChartEngine??
To solve the problem of having bar inside the graph we need to specify X-axis and Y-axis min and max based on your minimum and maximum values,eg; for the renderer, you need
renderer.setXAxisMin(-1);
renderer.setXAxisMax(wrongAnswers);
renderer.setYAxisMax(10);
renderer.setYAxisMin(0);
so the final result comes out to be
i'm using jfreechart, and i need to add labels to my series data. There are bold dots on graphic and they need labels... Following code does not work.
XYSeries series = new XYSeries("Average Size");
series.add(.60, .70);
XYDataset xyDataset = new XYSeriesCollection(series);
XYItemRenderer rend = new XYShapeRenderer();
XYItemLabelGenerator generator = new XYItemLabelGenerator() {
#Override
public String generateLabel(XYDataset xyd, int i, int i1) {
return "Some label?";
}
};
//SeriesItemLabelGenerator
rend.setBaseItemLabelGenerator(generator);
rend.setBaseItemLabelsVisible(true);
ItemLabelPosition pos = new ItemLabelPosition(ItemLabelAnchor.CENTER, TextAnchor.TOP_LEFT);
rend.setBasePositiveItemLabelPosition(pos);
I think the problem is that XYShapeRenderer(http://www.jfree.org/jfreechart/api/javadoc/src-html/org/jfree/chart/renderer/xy/XYShapeRenderer.html), which extends AbstractXYItemRenderer, does not implement ItemLabelGenerator logic yet.
So, or you will need to use another Renderer.
For example, XYLineAndShapeRenderer(http://www.jfree.org/jfreechart/api/javadoc/src-html/org/jfree/chart/renderer/xy/XYLineAndShapeRenderer.html) implements it:
// draw the item label if there is one...
if (isItemLabelVisible(series, item)) {
drawItemLabel(g2, orientation, dataset, series, item, xx, yy,(y1 < 0.0));
}
Or you will need to extend XYShapeRenderer yourself and add the label drawing logic, using any of the other Renderer's source code as an example.
I have a JFreeChart instance that displays process memory status, initialized as follows:
m_data = new TimeSeriesCollection();
TimeSeries vmsize = new TimeSeries("VMSize");
TimeSeries resident = new TimeSeries("Resisdent");
TimeSeries shared = new TimeSeries("Shared memory");
TimeSeries code = new TimeSeries("Code");
TimeSeries data = new TimeSeries("Data");
m_data.addSeries(vmsize);
m_data.addSeries(resident);
m_data.addSeries(shared);
m_data.addSeries(code);
m_data.addSeries(data);
JFreeChart chart = ChartFactory.createTimeSeriesChart("Memory usage", "Time", "Size", m_data, true, true, false);
m_chart = new ChartPanel(chart);
Later I add values to each TimeSeries in the TimeSeriesCollection. I would like to somehow know - when the user clicks on the Chart - either what time associated with that columm, or even better - what is the index of the value.
I looked at the JFreeChart and ChartMouseListener classes, but I could not figure out how to do that (also the documentation of JFreeChart is annoyingly scarce, I guess they are trying to get people to buy their developer's guide).
if you click dead on the item, the event.getEntity() function returns XYItem and then from there onwards
XYItemEntity xyitem=(XYItemEntity) event.getEntity(); // get clicked entity
XYDataset dataset = (XYDataset)xyitem.getDataset(); // get data set
System.out.println(xyitem.getItem()+" item of "+xyitem.getSeriesIndex()+"series");
System.out.println(dataset.getXValue(xyitem.getSeriesIndex(), xyitem.getItem()));
System.out.println(dataset.getYValue(xyitem.getSeriesIndex(), xyitem.getItem()));
Comparable comparable=dataset.getSeriesKey(0);
XYPlot xyplot = (XYPlot) event.getChart().getPlot();
System.out.println(xyplot.getRangeCrosshairValue());
however incase you do not click on the item itself but your crosshair is set to auto lock on data, in such case the crosshair will move to nearest item but since the item has not been clicked, you will not be able to get the XYItem and hence you cannot know the series and item index, to solve this problem there is this code below, it should be put in the catch clause while the above mentioned code should be in try clause
first define a function which will take crosshair value at domain and range and also Xydataset, this functions returns an inner class object that groups item index and series index
public static SeriesAndItemIndex getItemIndex(double domainVal,double rangeVal,XYDataset xydataset){
Comparable comparable;
int indexOf;
for(int i=0;i<xydataset.getSeriesCount();i++){
comparable = xydataset.getSeriesKey(i);
indexOf=xydataset.indexOf(comparable);
for(int j=0 ; j<xydataset.getItemCount(indexOf);j++){
double x=xydataset.getXValue(indexOf, j);
double y=xydataset.getYValue(indexOf, j);
if(x == domainVal && y==rangeVal){
return new SeriesAndItemIndex(j,indexOf);//return item index and series index
}
}
}
return null;
}
private static class SeriesAndItemIndex{ ///inner CLASS to group series and item clicked index
public int itemIndex;
public int seriesIndex;
public SeriesAndItemIndex(int i,int s){
itemIndex=i;
seriesIndex=s;
}
#Override
public String toString(){
return "itemIndex="+itemIndex+",seriesIndex="+seriesIndex;
}
}
how to use it?
try{......code block from the top
}catch(Exception e){
Object source=event.getSource();
JFreeChart chartpanel=(JFreeChart)source;
XYPlot xyplot = (XYPlot) chartpanel.getPlot();
XYDataset xydataset= xyplot.getDataset();
double d=xyplot.getDomainCrosshairValue(); //get crosshair X value
double r =xyplot.getRangeCrosshairValue(); //get crosshair y value
SeriesAndItemIndex index=getItemIndex(d,r,xydataset);
if(index != null){
System.out.println(index.toString());
}
}
hmm should work, if you replace the last two lines by something like this:
ChartPanel panel=new ChartPanel(ChartFactory.createTimeSeriesChart("Memory usage", "Time", "Size", m_data, true, true, false)));
panel.addChartMouseListener(new ChartMouseListener(){
void chartMouseClicked(ChartMouseEvent e){
[...do something on click...]
}
void chartMouseMoved(ChartMouseEvent e){
[...do something on move...]
}
});
return panel;