Reputation: 183
I am using JFreeCharts and I have both the legend and subtitles positioned at the top of the chart. However, my desire is to have the title, then the subtitle in the second line, and then the legend underneath. Instead, it has the title, then legend, and then subtitle. This is the current layout:
As you can see, the legend is above the subtitles, whereas it should be the other way around. All of this, the title, legend, and subtitles, should be above the chart.
My current code to make the chart and customize the titles, subtitles, and legend are:
public JFreeChart createStackedChart(final CategoryDataset categorydataset, String Title) throws DocumentException, IOException {
final JFreeChart chart = ChartFactory.createStackedBarChart(
Title, // chart title
"", // domain axis label
"", // range axis label
categorydataset, // data
PlotOrientation.VERTICAL, // the plot orientation
true, // legend
true, // tooltips
false // urls
);
chart.setTitle(
new org.jfree.chart.title.TextTitle(Title,
new java.awt.Font("Calibri", java.awt.Font.PLAIN, 12)
));
chart.getTitle().setPaint(Color.GRAY);
Color subExc = new Color(237,125,49);
chart.addSubtitle(new TextTitle("Title",
new Font("Calibri", Font.PLAIN, 12), subExc,
RectangleEdge.TOP, HorizontalAlignment.CENTER,
VerticalAlignment.TOP, RectangleInsets.ZERO_INSETS));
chart.addSubtitle(new TextTitle("Title2",
new Font("Calibri", Font.PLAIN, 12), Color.GRAY,
RectangleEdge.TOP, HorizontalAlignment.CENTER,
VerticalAlignment.TOP, RectangleInsets.ZERO_INSETS));
LegendTitle legend = chart.getLegend();
legend.setPosition(RectangleEdge.TOP);
chart.getLegend().setFrame(BlockBorder.NONE);
legend.setItemPaint(Color.GRAY);
Font labelFont = new Font("Calibri", Font.PLAIN, 8);
legend.setItemFont(labelFont);
int columnCount = categorydataset.getColumnCount();
chart.setBackgroundPaint(Color.white);
chart.getTitle().setPadding(10, 2, 0, 2);
chart.setBorderVisible(true);
chart.setBorderPaint(Color.lightGray);
final CategoryPlot plot = chart.getCategoryPlot();
plot.setBackgroundPaint(Color.white);
plot.setDomainGridlinePaint(Color.lightGray);
plot.setRangeGridlinePaint(Color.lightGray);
plot.setDomainGridlineStroke(new BasicStroke(0.5f));
plot.setRangeGridlineStroke(new BasicStroke(0.5f));
plot.setOutlineVisible(true);
plot.setOutlinePaint(Color.lightGray);
plot.setAxisOffset(new RectangleInsets(0, 0, 0, 0));
final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setTickLabelFont(new Font("Calibri", Font.PLAIN, 9));
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
rangeAxis.setAutoRangeStickyZero(false);
rangeAxis.setLowerMargin(0.0);
rangeAxis.setTickLabelPaint(Color.GRAY);
rangeAxis.setTickMarkPaint(Color.lightGray);
rangeAxis.setTickMarkStroke(new BasicStroke(0.3f));
rangeAxis.setAxisLineStroke(new BasicStroke(0.3f));
rangeAxis.setLowerBound(0.0f);
rangeAxis.setAxisLinePaint(Color.lightGray);
GroupedStackedBarRenderer renderer = new GroupedStackedBarRenderer();
renderer.setDrawBarOutline(false);
renderer.setBarPainter(new StandardBarPainter());
Paint p1 = new GradientPaint(
0.0f, 0.0f, new Color(0x22, 0x22, 0xFF), 0.0f, 0.0f, new Color(0x88, 0x88, 0xFF)
);
renderer.setSeriesPaint(0, p1);
renderer.setSeriesPaint(4, p1);
renderer.setSeriesPaint(8, p1);
Paint p2 = new GradientPaint(
0.0f, 0.0f, new Color(0x22, 0xFF, 0x22), 0.0f, 0.0f, new Color(0x88, 0xFF, 0x88)
);
renderer.setSeriesPaint(1, p2);
renderer.setSeriesPaint(5, p2);
renderer.setSeriesPaint(9, p2);
Paint p3 = new GradientPaint(
0.0f, 0.0f, new Color(0xFF, 0x22, 0x22), 0.0f, 0.0f, new Color(0xFF, 0x88, 0x88)
);
renderer.setSeriesPaint(2, p3);
renderer.setSeriesPaint(6, p3);
renderer.setSeriesPaint(10, p3);
Paint p4 = new GradientPaint(
0.0f, 0.0f, new Color(0xFF, 0xFF, 0x22), 0.0f, 0.0f, new Color(0xFF, 0xFF, 0x88)
);
renderer.setSeriesPaint(3, p4);
renderer.setSeriesPaint(7, p4);
renderer.setSeriesPaint(11, p4);
renderer.setGradientPaintTransformer(
new StandardGradientPaintTransformer(GradientPaintTransformType.HORIZONTAL)
);
final CategoryAxis domainAxis = plot.getDomainAxis();
domainAxis.setTickLabelPaint(Color.GRAY);
domainAxis.setTickLabelFont(new Font("Calibri", Font.PLAIN, 9));
Color transparent = new Color(0, 0, 0, 0);
domainAxis.setAxisLinePaint(transparent);
domainAxis.setTickMarkPaint(Color.lightGray);
domainAxis.setTickMarkStroke(new BasicStroke(0.3f));
domainAxis.setMaximumCategoryLabelWidthRatio(4f);
if (columnCount == 2) {
domainAxis.setCategoryMargin(.6);
domainAxis.setLowerMargin(0.015);
domainAxis.setUpperMargin(0.015);
} else if (columnCount == 3) {
domainAxis.setCategoryMargin(.35);
domainAxis.setLowerMargin(0.15);
domainAxis.setUpperMargin(0.15);
} else {
domainAxis.setCategoryMargin(.55);
domainAxis.setLowerMargin(0.015);
domainAxis.setUpperMargin(0.015);
}
if (columnCount >= 5) {
domainAxis.setCategoryLabelPositions(
CategoryLabelPositions.createUpRotationLabelPositions(Math.PI / 4.0));
chart.setPadding(new RectangleInsets(0, 5, 0, 5));
} else {
domainAxis.setCategoryLabelPositions(
STANDARD);
}
plot.setDomainAxis(domainAxis);
return chart;
}
What should I do besides RectangleEdge TOP to be able to determine the stacking order of the legend and subtitles? Thanks!
Upvotes: 1
Views: 783
Reputation: 4277
Here is a work-around that might do the trick for you:
chart.removeLegend();
ChartPanel
inside a JPanel
(with BorderLayout
)Should look like:
public static JPanel wrapChart(ChartPanel chartPanel) {
JPanel panel = new JPanel(new BorderLayout());
panel.add(chartPanel, BorderLayout.CENTER);
panel.add(createLegend(chartPanel.getChart().getPlot()), BorderLayout.SOUTH);
return panel;
}
private static JPanel createLegend(Plot plot) {
JPanel panel = new JPanel(); // Using FlowLayout here
Iterator iterator = plot.getLegendItems().iterator();
while (iterator.hasNext()) {
LegendItem item = (LegendItem) iterator.next();
JLabel label = new JLabel(item.getLabel());
label.setIcon(new ColorIcon(8, item.getFillPaint()));
panel.add(label);
}
return panel;
}
(createLegend()
method borrowed from this answer)
Upvotes: 1
Reputation: 183
Actually, I have found a solution. Just in case this helps others out there. The source of inspiration for the answer was found in:
http://www.jfree.org/phpBB2/viewtopic.php?f=3&t=23187
I had to change my code to incorporate this. I wrote
chart.addSubtitle(0,new TextTitle("Title",
new Font("Calibri", Font.PLAIN, 12), subExc,
RectangleEdge.TOP, HorizontalAlignment.CENTER,
VerticalAlignment.TOP, RectangleInsets.ZERO_INSETS));
chart.addSubtitle(1,new TextTitle("Title2",
new Font("Calibri", Font.PLAIN, 12), Color.GRAY,
RectangleEdge.TOP, HorizontalAlignment.CENTER,
VerticalAlignment.TOP, RectangleInsets.ZERO_INSETS));
Adding the 0 and 1 made these subtitles get written BEFORE the legend.
Upvotes: 2