Menu

#695 Item labels get cut (out of margin)

open
nobody
None
8
2014-08-28
2006-11-21
m.hilpert
No

If you have a chart that shows percentages, you obviously have a range axis 0% to 100% => range min value = 0.0, range max value = 100.0. For this reason we also don't want to have auto calculated range-axes but a fixed range 0.0 - 100.0 because the axes line shouldn't go higher than the 100 % max value. If you now have a category value of e.g. 99.5% and switch on the item labels, this label gets cut of at the top border. (Of course also depending on the font).

The item labels should be drawn independently of the inner plot border, so that such labels don't get cut but are drawn over the borders of the inner plot.

Test chart:

-----------------------------
/**
* This test shows that a bar label gets cut by the plots top border if a fixed range is used without margins and the bar is "too high" for the label.
* (E.g. for percenatge charts 0% to 100% you don't want margins but an exact range axis from 0% to 100% and not wider.)
*
* @return JFreeChart.
*/
private JFreeChart testBarLabelCut() {
JFreeChart result = null;

DefaultCategoryDataset cd = new DefaultCategoryDataset();
cd.addValue(50.3, "Series1", "Category1");
cd.addValue(99.99, "Series1", "Category2");

result = ChartFactory.createBarChart("Bar Chart", "Categories", "Values", cd, PlotOrientation.VERTICAL, false, false, false);

CategoryPlot plot = result.getCategoryPlot();
plot.getRangeAxis().setUpperMargin(0.0);
CategoryItemRenderer renderer = plot.getRenderer();
CategoryItemLabelGenerator generator = new StandardCategoryItemLabelGenerator("{2} %", NumberFormat.getInstance());
renderer.setItemLabelGenerator(generator);
renderer.setItemLabelsVisible(true);
renderer.setPositiveItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.OUTSIDE12, TextAnchor.CENTER, TextAnchor.CENTER, 0));

return result;
}//testBarLabelCut()
-------------------------------------

Discussion

  • m.hilpert

    m.hilpert - 2007-07-24

    Example chart with bar label cut.

     
  • m.hilpert

    m.hilpert - 2007-07-24

    Logged In: YES
    user_id=667728
    Originator: YES

    Still doesn't work with JFreeChart 1.0.6:

    /**
    * This test shows that a bar label gets cut by the plots top border if a fixed range is used without margins and the bar is "too high" for the label.
    * (E.g. for percenatge charts 0% to 100% you don't want margins but an exact range axis from 0% to 100% and not wider.)
    *
    * @return JFreeChart.
    */
    private JFreeChart testBarLabelCut() {
    JFreeChart result = null;

    DefaultCategoryDataset cd = new DefaultCategoryDataset();
    cd.addValue(50.3, "Series1", "Category1");
    cd.addValue(99.99, "Series1", "Category2");

    result = ChartFactory.createBarChart("Bar Chart", "Categories", "Values", cd, PlotOrientation.VERTICAL, false, false, false);

    CategoryPlot plot = result.getCategoryPlot();
    plot.getRangeAxis().setUpperMargin(0.0);
    CategoryItemRenderer renderer = plot.getRenderer();
    CategoryItemLabelGenerator generator = new StandardCategoryItemLabelGenerator("{2} %", NumberFormat.getInstance());
    renderer.setSeriesItemLabelGenerator(0, generator); //0 = 1st series
    renderer.setSeriesItemLabelsVisible(0, true);
    renderer.setSeriesPositiveItemLabelPosition(0, new ItemLabelPosition(ItemLabelAnchor.OUTSIDE12, TextAnchor.CENTER, TextAnchor.CENTER, 0));

    return result;
    }//testBarLabelCut()
    File Added: screenshot.png

     
  • m.hilpert

    m.hilpert - 2007-07-24
    • priority: 5 --> 6
     
  • m.hilpert

    m.hilpert - 2007-07-24

    Logged In: YES
    user_id=667728
    Originator: YES

    Here's a test version with a workaround I've found. It's ugly but at least the labels don't get cut anymore (hopefully for most cases ...). The fix is disabled by default - so compare it by simply toggle the "if (false) {" line:

    -----------------------------------------------

    /**
    * This test shows that a bar label gets cut by the plots top border when no explicit margins are set and the bar is "too high" for the label.
    * (E.g. for percentage charts 0% to 100%). The resulting chart is displayed in ChartPanel within a 300x400 JFrame.
    *
    * @return JFreeChart.
    */
    private JFreeChart testBarLabelCut() {
    JFreeChart result = null;

    final int indexSeries = 0;
    final DefaultCategoryDataset cd = new DefaultCategoryDataset();
    cd.addValue(864.4, "Series "+indexSeries, "Category1");
    cd.addValue(-709.7, "Series "+indexSeries, "Category2");

    result = ChartFactory.createBarChart("Bar Chart", "Categories", "Values", cd, PlotOrientation.VERTICAL, false, false, false);

    final CategoryPlot plot = result.getCategoryPlot();
    final ValueAxis va = plot.getRangeAxis();
    final CategoryItemRenderer renderer = plot.getRenderer();
    final CategoryItemLabelGenerator generator = new StandardCategoryItemLabelGenerator("{2} %", NumberFormat.getInstance());
    renderer.setSeriesItemLabelGenerator(indexSeries, generator); //0 = 1st series
    renderer.setSeriesItemLabelsVisible(indexSeries, true);
    renderer.setSeriesPositiveItemLabelPosition(indexSeries, new ItemLabelPosition(ItemLabelAnchor.OUTSIDE12, TextAnchor.BOTTOM_CENTER, TextAnchor.CENTER, 0));

    if (false) { //enable fix?
    //****************** fix label cutting: *******************************************************
    if (renderer.isSeriesItemLabelsVisible(indexSeries)) {
    //some production attributes to set:
    final boolean includeZero = true; //we want full bars
    final double chartHeight = 300;
    final Font font = new Font("Helvetica", Font.PLAIN, 6);

    //start of fix:
    double min = DatasetUtilities.findMinimumRangeValue(cd).doubleValue();
    double max = DatasetUtilities.findMaximumRangeValue(cd).doubleValue();
    if (includeZero) {
    min = 0 < min ? 0 : min;
    max = max < 0 ? 0 : max;
    }
    double r = max - min; //full range from min to max

    final double f = font.getSize() / chartHeight; //margin %
    final double margin = (0.1 + f) * r; //10% + font size of full range
    double marginTop = 0.0;
    double marginBottom = 0.0;
    if (max > 0) { //positive labels?
    marginTop = margin;
    }
    if (min < 0) { //negative labels?
    marginBottom = margin;
    }

    va.setRange(min - marginBottom, max + marginTop);
    }//else: item labels unvisible => no fix required
    }

    return result;
    }//testBarLabelCut()
    ------------------------------------

    File Added: screenshot.png

     
  • m.hilpert

    m.hilpert - 2007-07-24

    Left chart: without fix; right chart: with fix.

     
  • m.hilpert

    m.hilpert - 2008-01-30
    • priority: 6 --> 8
     

Log in to post a comment.