Search code examples
chartsjasper-reportsjfreechart

Custom value labels on top of bars with Jasper Report bar charts


I have defined a bar chart in Jasper Studio and it's generating this kind of result:

enter image description here

The values on top of bars are overlapping. I would like either of:

  • reduce labels' text size and limit them to two decimal places.
  • change the vertical position of labels to avoid overlapping.

I'm not sure but I think that Jasper Studio doesn't allow to configure any of it.

I've seen about implementing in code JRChartCustomizer but I don't know how to modify labels' texts or positions.

EDIT

I've tried this way:

    public void customize(JFreeChart fc, JRChart jrc) {
    
    CategoryPlot catPlot = fc.getCategoryPlot();
    
    if (jrc.getDataset() instanceof JRFillChartDataset) {
        JRFillChartDataset jrFillChartDataset = (JRFillChartDataset) jrc.getDataset();

        CategoryLabelGenerator categoryLabelGenerator = (CategoryLabelGenerator) jrFillChartDataset.getLabelGenerator();
        categoryLabelGenerator.getNumberFormat().setMaximumFractionDigits(1);

But is useless because getLabelGenerator() creates a new CategoryLabelGenerator on each calling so setting values to its NumberFormat instance is pointless.


Solution

  • Finally I got it like this:

    @Override
    public void customize(JFreeChart fc, JRChart jrc) {
        
        CategoryPlot catPlot = fc.getCategoryPlot();
    
        
        final CategoryItemRenderer renderer = catPlot.getRenderer();
        Font font = renderer.getBaseItemLabelFont();
        Font font2 = font.deriveFont(3f);
        renderer.setBaseItemLabelFont(font2);
        
        renderer.setBaseItemLabelGenerator(new CategoryLabelGenerator(null) {
            private static final long serialVersionUID = 549073036018846176L;
    
            @Override
            public String generateLabel(CategoryDataset dataset, int row, int column) {
                Number value = dataset.getValue(row, column);
                
                if (value != null) {
                    
                    NumberFormat nf = NumberFormat.getPercentInstance();
                    nf.setMinimumIntegerDigits(1);
                    nf.setMaximumFractionDigits(2);
                    
                    return nf.format(value.doubleValue() / 100);
                }
                
                return null;
            }
        });
    }