Search code examples
javajfreechart

Bar chart with exact value printed on top of each bar


Is there a way to accomplish the following in JFreeChart?

I am specifically asking about the elegantly printed numbers at the top of each bar. In this particular specimen it is easy to guess the values but such a feature would be useful if the y-axis run in the thousands or more. In such a case, the length of the bar wouldn't much help to discover the exact value.

enter image description here


Solution

  • Yes, it is possible. You need to specify ItemLabelPosition in CategoryItemLabelGenerator.

    For example:

    renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator());
    renderer.setBaseItemLabelsVisible(true);
    ItemLabelPosition position = new ItemLabelPosition(ItemLabelAnchor.OUTSIDE12, 
            TextAnchor.TOP_CENTER);
    renderer.setBasePositiveItemLabelPosition(position);
    

    EDIT:

    enter image description here

    import javax.swing.JFrame;
    import javax.swing.SwingUtilities;
    
    import org.jfree.chart.ChartFactory;
    import org.jfree.chart.ChartPanel;
    import org.jfree.chart.JFreeChart;
    import org.jfree.chart.labels.ItemLabelAnchor;
    import org.jfree.chart.labels.ItemLabelPosition;
    import org.jfree.chart.labels.StandardCategoryItemLabelGenerator;
    import org.jfree.chart.plot.CategoryPlot;
    import org.jfree.chart.plot.PlotOrientation;
    import org.jfree.chart.renderer.category.CategoryItemRenderer;
    import org.jfree.data.category.DefaultCategoryDataset;
    import org.jfree.ui.TextAnchor;
    
    public class DemoBarChart {
        public DemoBarChart() {
            DefaultCategoryDataset dataset = new DefaultCategoryDataset();
            dataset.setValue(6, "test", "A");
            dataset.setValue(7, "test", "B");
            dataset.setValue(15, "test", "C");
    
            JFreeChart chart = ChartFactory.createBarChart(
                    "Demo", "Test", "Value", dataset,
                    PlotOrientation.VERTICAL, false, false, false);
    
            CategoryItemRenderer renderer = ((CategoryPlot)chart.getPlot()).getRenderer();
    
            renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator());
            renderer.setBaseItemLabelsVisible(true);
            ItemLabelPosition position = new ItemLabelPosition(ItemLabelAnchor.OUTSIDE12, 
                    TextAnchor.TOP_CENTER);
            renderer.setBasePositiveItemLabelPosition(position);
    
            JFrame frame = new JFrame("DemoTable");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(new ChartPanel(chart));
            frame.setLocationByPlatform(true);
            frame.pack();
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    new DemoBarChart();
                }
            });
        }
    }
    

    EDIT (version 1.5.0):

    In current JFreeChart version (1.5.0), the "Base" in methods name has changed to Default.

    For example:

    renderer.setDefaultItemLabelGenerator(new StandardCategoryItemLabelGenerator());
    renderer.setDefaultItemLabelsVisible(true);
    ItemLabelPosition position = new ItemLabelPosition(ItemLabelAnchor.OUTSIDE12, 
            TextAnchor.TOP_CENTER);
    renderer.setDefaultPositiveItemLabelPosition(position);