Amila Iddamalgoda
Amila Iddamalgoda

Reputation: 4286

JFreeChart | How to add percentage to top of each bar and format domain axis (X axis) ticklabels?

I'm using JFreeChart and following is a screenshot of the developed chart by me and the related code.

JFreeChart

    private void getBarChart(List<Data> data) {
JFreeChart barChart = ChartFactory.createBarChart("", "", "", createDataset(data), PlotOrientation.VERTICAL, false, true, false);
        CategoryPlot plot = barChart.getCategoryPlot();
        plot.getRenderer().setSeriesPaint(0, new Color(7, 43, 97));

        barChart.getCategoryPlot().getRangeAxis().setLowerBound(0);
        barChart.getCategoryPlot().getRangeAxis().setUpperBound(1);
        NumberAxis xAxis2 = (NumberAxis) barChart.getCategoryPlot().getRangeAxis();
        xAxis2.setNumberFormatOverride(NumberFormat.getPercentInstance());

        plot.getRenderer().setSeriesItemLabelGenerator(0, new StandardCategoryItemLabelGenerator());
        plot.getRenderer().setSeriesItemLabelsVisible(1, true);
        plot.getRenderer().setBaseItemLabelsVisible(true);
        plot.getRenderer().setBaseSeriesVisible(true);
        barChart.getCategoryPlot().setRenderer(plot.getRenderer());


        BarRenderer.setDefaultBarPainter(new StandardBarPainter());
        ((BarRenderer) plot.getRenderer()).setBarPainter(new StandardBarPainter());

        BufferedImage image = new BufferedImage(650, 250, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = image.createGraphics();
        g2.setRenderingHint(JFreeChart.KEY_SUPPRESS_SHADOW_GENERATION, true);
        Rectangle r = new Rectangle(0, 0, 650, 250);
        barChart.draw(g2, r);
        BufferedImage chartImage = barChart.createBufferedImage(600, 400, null);
}

The expected chart should be something like following. enter image description here

Question 1.) How to format the x axis lables as per like the expected graph ?(CategoryLables or TickLabels in barChart.getCategoryPlot().getDomainAxis())

Question 2.) The values displayed in top of each bar (SeriesItemLabels) needs to be formatted with a percentage mark(%) similar to the y axis. (Also I think, like I have done in xAxis2.setNumberFormatOverride, the values will automatically get multipled by 100%. Right now it displays the decimal value only). How to achieve this ?

Please help me out. Thanks.

Upvotes: 3

Views: 2916

Answers (2)

trashgod
trashgod

Reputation: 205795

Working from BarChartDemo1.java, updated for JFreechart 1.5, the following alternative are illustrated below.

  1. As shown here and here, you can invoke setCategoryLabelPositions() on the domain axis and use CategoryLabelPositions.createUpRotationLabelPositions to fine-tune the angle. The example below rotates counter-clockwise π/4 radians or 45°.

    CategoryAxis domainAxis = plot.getDomainAxis();
    domainAxis.setCategoryLabelPositions(
        CategoryLabelPositions.createUpRotationLabelPositions(Math.PI / 4.0));
    
  2. A shown here, you can construct a custom StandardCategoryItemLabelGenerator, but you may want to use ArgumentIndex {3}, which is the value as a percentage of the column total, as well as a suitable NumberFormat.

    renderer.setDefaultItemLabelGenerator(
        new StandardCategoryItemLabelGenerator(
            "{3}", NumberFormat.getPercentInstance()));
    renderer.setDefaultItemLabelsVisible(true);
    

bar chart

Upvotes: 4

Topaco
Topaco

Reputation: 49251

1) The following line enables the axis-labels with an ascending slope:

CategoryAxis domainAxis = plot.getDomainAxis();  
domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45);

45 denotes the angle in degree and UP means an orientation from bottom left to top right. You can also define an arbitrary angle (e.g. 22.5°) with

CategoryAxis domainAxis = plot.getDomainAxis();  
domainAxis.setCategoryLabelPositions(CategoryLabelPositions.createUpRotationLabelPositions(Math.toRadians(22.5))); 

It should be noted that createUpRotationLabelPositions expects an angle in radians.

2) The following line formats the bar-labels of series 0 in percent.

DecimalFormat labelFormat = new DecimalFormat("##0.0 %");
labelFormat.setMultiplier(100);
plot.getRenderer().setSeriesItemLabelGenerator(0, new StandardCategoryItemLabelGenerator("{2}", labelFormat));
plot.getRenderer().setSeriesItemLabelsVisible(0, true);

with {0} = series, {1} = category, {2} = value

As an alternative you can define your own label generator, e.g.:

class CstmStandardCategoryItemLabelGenerator extends StandardCategoryItemLabelGenerator {

    @Override
    public String generateLabel(CategoryDataset dataset, int row, int column) {
        return String.format("%.1f %%", dataset.getValue(row, column).doubleValue() * 100.0);
    }
}

which simply can be used as follows:

plot.getRenderer().setSeriesItemLabelGenerator(0, new CstmStandardCategoryItemLabelGenerator());

This results in:

enter image description here

Upvotes: 3

Related Questions