Adding text not related to sections into Legend in

2020-05-30 02:41发布

问题:

Is there a way to include some arbitrary text in the legend in a JFreeChart PieChart? I know it's possible to assign a PieSectionLabelGenerator in order to customize the labels of each of the Pie's sections that appear on the chart's legend.

I'd like to insert some text into the legend, completely unrelated to any of the pie sections, like, for instance, "Legend".

I'm building the Chart like this:

private JFreeChart constructChart() {
    List<Object[]> llistaValorsArr;

    ParamsDTO dto = (ParamsDTO) getModelObject();
    List llistaValors = statisticsService.getStatistics(dto);
    if (!llistaValors.isEmpty() && !(llistaValors.get(0) instanceof Object[])){
        llistaValorsArr = new ArrayList<Object[]>();
        llistaValorsArr.add(new Object[]{llistaValors.get(0), ""});
    }
    else{
        llistaValorsArr = (List<Object[]>) llistaValors;
    }
    DefaultPieDataset dataSet = new DefaultPieDataset();
    for (Object[] objects : llistaValorsArr) {
        dataSet.setValue((Comparable) objects[1], (Number)objects[0]);
    }

    String title = "Total: " +  new Double(DatasetUtilities.calculatePieDatasetTotal(dataSet)).intValue();
    JFreeChart chart = ChartFactory.createPieChart(title, dataSet, true, false, true);

    final PiePlot plot = (PiePlot) chart.getPlot();
    plot.setForegroundAlpha(0.5f);
    plot.setNoDataMessage("No data");

    PieSectionLabelGenerator labelGenerator = new StandardPieSectionLabelGenerator("{0} - {1} ({2})"){
        @Override
        protected Object[] createItemArray(PieDataset dataset, Comparable key) {
            // TODO Auto-generated method stub
            Object[] array = super.createItemArray(dataset, key);
            array[0] = getEntityLabel(key);
            return array;
        }
    };
    plot.setLabelGenerator(labelGenerator);
    plot.setLegendLabelGenerator(labelGenerator);        
    //plot.setStartAngle(290);
    boolean circular = true;
    plot.setCircular(circular);
    return chart;
}

UPDATE: I just found out JFreeChart.addSubtitle(), hoping it would allow to position it just above the legend, but it will just add a subtitle next to the chart's Title.

UPDATE 2: I've been trying to place a TextTitle inside the LegendTitle's wrapper, but it appears to be null at chart construction time.

LegendTitle legend = chart.getLegend();
BlockContainer container = legend.getWrapper();
container.add(new TextTitle("Legend"));

It shouldn't really be that complicated to add a 'Legend' text to decorate the legend.

回答1:

Looking at the source code of org.jfree.chart.JFreeChart, and seeing that addLegend() is nothing more than addSubtitle() behind the scenes, everything indicates that this should be achieved using addSubtitle().

Looking at the part where org.jfree.chart.JFreeChart adds its own LegendTitle item, we can find the setup JFreeChart uses for placing the Legend here.

So, the solution is to add, for instance, a TextTitle to the Chart in an analogous way. The relevant setting here is setPosition(RECTANGLE.BOTTOM).

TextTitle legendText = new TextTitle("This is LEGEND: ");
legendText.setPosition(RectangleEdge.BOTTOM);
chart.addSubtitle(legendText);


回答2:

I have a Multi Axis chart that i recently built and came up with this scheme to distinguish the time periods i was displaying using a line chart to show the previous 12 months imposed over a bar chart showing the current 12 months.

If you want to add text before your other series so that your legend looks something like this:

Previous 12 Months: * charges * adj * cash Current 12 Months: * charges * adj * cash

where the *'s are the shapes/colors of your series. (i would have included a pic, but i dont have enough rep points ... this is my first post to stack overflow =) )

Then i would suggest adding a series and making it the first series in your chart(s) (series 0). Name this series whatever text you want to display (my example is "Previous 12 Months: ". Then you can use some java to customize series 0 so that the data is not show on the chart, but you still get the label in the legend.

This is what my custmoize method for making a line chart line/shape not visible:

@Override
public void customize(JFreeChart chart, JRChart jasperChart) {
    LineAndShapeRenderer renderer = (LineAndShapeRenderer) chart.getCategoryPlot().getRenderer();

    renderer.setSeriesLinesVisible(0, false);
    renderer.setSeriesShapesVisible(0, false);

    etc ....
}

If it is another type of chart like the bar chart then just make series 0's color to match the background and give it a value like 1. Note that this does add more space between the bars! The extra space between the bars on my chart made it look better, but this wouldn't be a good solution if you like the spacing between your charts bars.

Not sure if this is useful for answering the initial question but its another option for anyone looking to add text the their charts legend.

Enjoy!



回答3:

Another possibility is to create a class implementing the interface org.jfree.chart.LegendItemSource which provides all your additional legend items. Then you add your own LegendItemSource to your LegendTitle object (the only other item source is the PieChart).

chart.getLegend().setSources(sourcesContainingTheOriginalAndYourNewOne);

If you want to control where to place the legend items or in which orderm of each item source, you can override LegendTitle.