• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

JFreeChart : Item Label in STack Bar Chart

 
Ranch Hand
Posts: 88
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi ,
I am using JFreeChart(ver 0.9.21) for generating Group Stacked Bar Charts for my Application .

I come across a problem for which i had no answer .

In the GroupStacked Bar Chart, i need to display the data values for each stck of the bar .
Upto this point things are going fine, next i need to show at the top of the Stacked Bar the
total of the stack values , which i am unable to do .

TO further clarify take an example :
Country Average Production
USA 80
UK 55
India 40 .

So i need to draw a stacked bar chart for this case which will show the resopective data values
for each & at the top of the Stacked bar display the total which in this case comes out to be 175.

Pls. help me out for this .
ASAP.
Thanks in Advance ,
Mohit
 
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Mohit,

I have a solution which worked for me on a recent projet.

Basically what I did was extended the StackedBarRender3D and override the drawStackVertical method.
Looking at the cource code of StackedBarRenderer3D, the last step in the drawStackVertical method is
to draw the item labels, which makes it very easy to add an extra step in my custom class to draw a new
label.

Things to note are that the calculateLabelAnchorPoint was copied from org.jfree.chart.renderer.category.BarRenderer
as the method is a private method in the BarRender class.
The createFrontFace method contains code which was copied from the StackedBarRenderer3D class, however modified to only
calulate the path which makes up the front face of the stack.

public class CustomStackedBarRenderer3D extends StackedBarRenderer3D
{
private static final long serialVersionUID = 1L;

private boolean categoryTotal = false;

private static final int TOTAL_LABEL_OFFSET = -10;

public CustomStackedBarRenderer3D() {
super();
}

public boolean getCategoryTotal() {
return categoryTotal;
}

public void setCategoryTotal(boolean value) {
categoryTotal = value;
}

protected void drawStackVertical(List values, Comparable category,
Graphics2D g2, CategoryItemRendererState state,
Rectangle2D dataArea, CategoryPlot plot,
CategoryAxis domainAxis, ValueAxis rangeAxis,
CategoryDataset dataset) {

super.drawStackVertical(values, category, g2, state, dataArea, plot, domainAxis, rangeAxis, dataset);

if(getCategoryTotal()) {
// draw our total item label. The drawItemLabel method exists in the BarRenderer class.
ItemLabelPosition position = null;

// get the column and the last row.
int column = dataset.getColumnIndex(category);
int row = dataset.getRowCount();

// calculate the total value and convert to a string for the label.
double total = DataUtilities.calculateColumnTotal(dataset, dataset.getColumnIndex(category));

// if the total is zero, the don't draw a label.
if(total <= 0.0d)
return;

// only show total if there are three or more values in the stack.
if(values.size() < 3)
return;

System.out.println("For the label " + Double.toString(total) + " size of values is: " + values.size() );
String label = Double.toString(total);

// get the label position.
position = getPositiveItemLabelPosition(row, column);

// calculate the bounds of the stack.
double barX0 = domainAxis.getCategoryMiddle(column,
dataset.getColumnCount(), dataArea, plot.getDomainAxisEdge())
- state.getBarWidth() / 2.0;
double barW = state.getBarWidth();
int blockCount = values.size() - 1;
Object[] prev = (Object[]) values.get(blockCount - 1);
Object[] curr = (Object[]) values.get(blockCount);
double v0 = ((Double) prev[1]).doubleValue();
double vv0 = rangeAxis.valueToJava2D(v0, dataArea,
plot.getRangeAxisEdge());
double v1 = ((Double) curr[1]).doubleValue();
double vv1 = rangeAxis.valueToJava2D(v1, dataArea,
plot.getRangeAxisEdge());

Shape frontFace = createFrontFace(barX0, barW, vv0, vv1);

// get anchor point i.e. bottom left of the label.
Point2D anchorPoint = calculateLabelAnchorPoint(
ItemLabelAnchor.OUTSIDE12, frontFace.getBounds2D(), plot.getOrientation());

anchorPoint.setLocation(anchorPoint.getX(), anchorPoint.getY() + TOTAL_LABEL_OFFSET);

// draw the label.
TextUtilities.drawRotatedString(label, g2,
(float) anchorPoint.getX(), (float) anchorPoint.getY(),
position.getTextAnchor(), position.getAngle(),
position.getRotationAnchor());
}
}

/**
* Calculates the path which makes up the front face of the stack.
* Taken from the StackedBarRenderer3D class.
*/
private Shape createFrontFace(double x0, double width, double y0, double y1) {
Point2D p00 = new Point2D.Double(x0, y0);
Point2D p01 = new Point2D.Double(x0 + width, y0);
Point2D p0 = new Point2D.Double(x0, y1);
Point2D p1 = new Point2D.Double(x0 + width, y1);

GeneralPath front = new GeneralPath();
front.moveTo((float) p0.getX(), (float) p0.getY());
front.lineTo((float) p1.getX(), (float) p1.getY());
front.lineTo((float) p01.getX(), (float) p01.getY());
front.lineTo((float) p00.getX(), (float) p00.getY());
front.closePath();

return front;
}

/**
* Calculates the item label anchor point. Taken from org.jfree.chart.renderer.category.BarRenderer
*
* @param anchor the anchor.
* @param bar the bar.
* @param orientation the plot orientation.
*
* @return The anchor point.
*/
private Point2D calculateLabelAnchorPoint(ItemLabelAnchor anchor,
Rectangle2D bar,
PlotOrientation orientation) {

Point2D result = null;
double offset = getItemLabelAnchorOffset();
double x0 = bar.getX() - offset;
double x1 = bar.getX();
double x2 = bar.getX() + offset;
double x3 = bar.getCenterX();
double x4 = bar.getMaxX() - offset;
double x5 = bar.getMaxX();
double x6 = bar.getMaxX() + offset;

double y0 = bar.getMaxY() + offset;
double y1 = bar.getMaxY();
double y2 = bar.getMaxY() - offset;
double y3 = bar.getCenterY();
double y4 = bar.getMinY() + offset;
double y5 = bar.getMinY();
double y6 = bar.getMinY() - offset;

if (anchor == ItemLabelAnchor.CENTER) {
result = new Point2D.Double(x3, y3);
}
else if (anchor == ItemLabelAnchor.INSIDE1) {
result = new Point2D.Double(x4, y4);
}
else if (anchor == ItemLabelAnchor.INSIDE2) {
result = new Point2D.Double(x4, y4);
}
else if (anchor == ItemLabelAnchor.INSIDE3) {
result = new Point2D.Double(x4, y3);
}
else if (anchor == ItemLabelAnchor.INSIDE4) {
result = new Point2D.Double(x4, y2);
}
else if (anchor == ItemLabelAnchor.INSIDE5) {
result = new Point2D.Double(x4, y2);
}
else if (anchor == ItemLabelAnchor.INSIDE6) {
result = new Point2D.Double(x3, y2);
}
else if (anchor == ItemLabelAnchor.INSIDE7) {
result = new Point2D.Double(x2, y2);
}
else if (anchor == ItemLabelAnchor.INSIDE8) {
result = new Point2D.Double(x2, y2);
}
else if (anchor == ItemLabelAnchor.INSIDE9) {
result = new Point2D.Double(x2, y3);
}
else if (anchor == ItemLabelAnchor.INSIDE10) {
result = new Point2D.Double(x2, y4);
}
else if (anchor == ItemLabelAnchor.INSIDE11) {
result = new Point2D.Double(x2, y4);
}
else if (anchor == ItemLabelAnchor.INSIDE12) {
result = new Point2D.Double(x3, y4);
}
else if (anchor == ItemLabelAnchor.OUTSIDE1) {
result = new Point2D.Double(x5, y6);
}
else if (anchor == ItemLabelAnchor.OUTSIDE2) {
result = new Point2D.Double(x6, y5);
}
else if (anchor == ItemLabelAnchor.OUTSIDE3) {
result = new Point2D.Double(x6, y3);
}
else if (anchor == ItemLabelAnchor.OUTSIDE4) {
result = new Point2D.Double(x6, y1);
}
else if (anchor == ItemLabelAnchor.OUTSIDE5) {
result = new Point2D.Double(x5, y0);
}
else if (anchor == ItemLabelAnchor.OUTSIDE6) {
result = new Point2D.Double(x3, y0);
}
else if (anchor == ItemLabelAnchor.OUTSIDE7) {
result = new Point2D.Double(x1, y0);
}
else if (anchor == ItemLabelAnchor.OUTSIDE8) {
result = new Point2D.Double(x0, y1);
}
else if (anchor == ItemLabelAnchor.OUTSIDE9) {
result = new Point2D.Double(x0, y3);
}
else if (anchor == ItemLabelAnchor.OUTSIDE10) {
result = new Point2D.Double(x0, y5);
}
else if (anchor == ItemLabelAnchor.OUTSIDE11) {
result = new Point2D.Double(x1, y6);
}
else if (anchor == ItemLabelAnchor.OUTSIDE12) {
result = new Point2D.Double(x3, y6);
}

return result;

}

}
 
author
Posts: 3285
13
Mac OS X Eclipse IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Chris and welcome to Javaranch!

Thanks for posting a answer for others to share (although the original Q was in 2005, so I'm not sure Mohit will see it!). Just so you know you can also use [code ] [ /code] (remove the space) tags to highlight your code samples.
 
Rototillers convert rich soil into dirt. Please note that this tiny ad is not a rototiller:
a bit of art, as a gift, the permaculture playing cards
https://gardener-gift.com
reply
    Bookmark Topic Watch Topic
  • New Topic