关于java:在JFreeChart PieChart中将与节无关的文本添加到图例中

Adding text not related to sections into Legend in JFreeChart PieChart

有没有办法在 JFreeChart PieChart 的图例中包含一些任意文本?我知道可以分配一个 PieSectionLabelGenerator 来自定义出现在图表图例上的每个饼图部分的标签。

我想在图例中插入一些与任何饼图部分完全无关的文本,例如"图例"。

我正在像这样构建图表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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;
}

更新:我刚刚发现 JFreeChart.addSubtitle(),希望它允许将其定位在图例上方,但它只会在图表标题旁边添加一个副标题。

更新 2:我一直试图在 LegendTitle 的package器中放置一个 TextTitle,但在图表构建时它似乎为空。

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

添加一个"图例"文本来装饰图例应该没有那么复杂。


查看org.jfree.chart.JFreeChart的源码,发现addLegend()在幕后无非是addSubtitle(),一切都表明这应该是使用addSubtitle()来实现的。

查看org.jfree.chart.JFreeChart添加自己的LegendTitle项的部分,我们可以找到JFreeChart用于放置图例的设置。

因此,解决方案是以类似的方式将 TextTitle 添加到 Chart 中。这里的相关设置是 setPosition(RECTANGLE.BOTTOM).

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

我有一个我最近构建的多轴图表,并提出了这个方案来区分我使用折线图显示的时间段,以显示前 12 个月强加于显示当前 12 个月的条形图。

如果您想在您的其他系列之前添加文本,以便您的图例看起来像这样:

前 12 个月:* 费用 * adj * 现金 当前 12 个月:* 费用 * adj * 现金

*\\ 是您的系列的形状/颜色。 (我会附上一张照片,但我没有足够的代表点......这是我第一篇关于堆栈溢出的帖子=))

然后我建议添加一个系列并将其作为图表中的第一个系列(系列 0)。将此系列命名为您要显示的任何文本(我的示例是 "Previous 12 Months: "。然后您可以使用一些 java 自定义系列 0,以便数据不会显示在图表上,但您仍然可以在传奇。

这是我用于使折线图线条/形状不可见的自定义方法:

1
2
3
4
5
6
7
8
9
@Override
public void customize(JFreeChart chart, JRChart jasperChart) {
    LineAndShapeRenderer renderer = (LineAndShapeRenderer) chart.getCategoryPlot().getRenderer();

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

    etc ....
}

如果它是另一种类型的图表,例如条形图,那么只需将系列 0 的颜色设置为与背景匹配,并给它一个类似 1 的值。请注意,这确实会增加条形之间的空间!我的图表上条形之间的额外空间使它看起来更好,但如果您喜欢图表条之间的间距,这不是一个好的解决方案。

不确定这对于回答最初的问题是否有用,但对于希望在图表图例中添加文本的人来说,这是另一种选择。

享受吧!


另一种可能性是创建一个实现接口 org.jfree.chart.LegendItemSource 的类,该接口提供所有额外的图例项。然后将您自己的 LegendItemSource 添加到您的 LegendTitle 对象(唯一的其他项目来源是 PieChart)。

1
chart.getLegend().setSources(sourcesContainingTheOriginalAndYourNewOne);

如果你想控制图例项目的放置位置或每个项目源的顺序,你可以覆盖 LegendTitle。