我在使用 jFreeChart(1.0.14,最新的 maven 版本)时遇到了一个小布局问题。由于图像在这里比文字更重要:
注意条形相对于子标签“A”、“B”、“C”、“D”的垂直位移。我不确定这是错误还是配置错误。请参阅下面附加的代码以进行复制。
此代码是从我当前的项目中取出的,因此其中可能有一些不必要的东西。
package de.test;
import java.awt.Color;
import java.awt.Font;
import java.awt.GradientPaint;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryLabelPosition;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.axis.CategoryLabelWidthType;
import org.jfree.chart.axis.SubCategoryAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.GroupedStackedBarRenderer;
import org.jfree.data.KeyToGroupMap;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.text.TextBlockAnchor;
import org.jfree.ui.RectangleAnchor;
import org.jfree.ui.TextAnchor;
public class MainFrame extends JFrame {
private static final long serialVersionUID = 5309704066433738856L;
private ChartPanel panel;
public static void main(String[] args) {
new MainFrame();
}
public MainFrame() {
JMenuBar menuBar = new JMenuBar();
setDefaultCloseOperation(EXIT_ON_CLOSE);
JFreeChart chart = ChartFactory.createStackedBarChart("", "", "", null, PlotOrientation.HORIZONTAL, false, true, false);
chart.setBackgroundPaint(getBackground());
chart.setTextAntiAlias(true);
panel = new ChartPanel(chart, 400, 400, 100, 100, 1000, 1000, true, false, false, true, false, false);
Set<String> subCategories = new TreeSet<>();
GroupedStackedBarRenderer groupedStackedBarRenderer = new GroupedStackedBarRenderer();
groupedStackedBarRenderer.setDrawBarOutline(true);
GradientPaint billPaint = new GradientPaint(0.0F, 0.0F, Color.GREEN.darker(), 0.0F, 0.0F, Color.GREEN);
GradientPaint creditPaint = new GradientPaint(0.0F, 0.0F, Color.RED.darker(), 0.0F, 0.0F, Color.RED);
SubCategoryAxis subCategoryAxis = new SubCategoryAxis(null);
subCategoryAxis.setCategoryLabelPositions(CategoryLabelPositions.replaceLeftPosition( //
subCategoryAxis.getCategoryLabelPositions(), //
new CategoryLabelPosition(RectangleAnchor.CENTER, TextBlockAnchor.BOTTOM_CENTER, TextAnchor.BOTTOM_CENTER, -Math.PI / 2,
CategoryLabelWidthType.CATEGORY, 1f)));
subCategoryAxis.setMinorTickMarksVisible(false);
subCategoryAxis.setAxisLineVisible(false);
subCategoryAxis.setTickLabelFont(subCategoryAxis.getLabelFont().deriveFont(Font.BOLD));
KeyToGroupMap keyToGroupMap = new KeyToGroupMap();
Map<String, Map<String, Map<String, Double>>> map = generateRandomSet(new HashSet<>(Arrays.asList("ab", "cd", "ef", "gh")),
new HashSet<>(Arrays.asList("A", "B", "C", "D")));
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
for (String employee : map.keySet()) {
Map<String, Map<String, Double>> classMap = map.get(employee);
for (String serviceClass : classMap.keySet()) {
Map<String, Double> typeMap = classMap.get(serviceClass);
subCategories.add(serviceClass.toString());
Double billValue = typeMap.containsKey("RE") ? (Double) typeMap.get("RE") : 0D;
Double creditNoteValue = typeMap.containsKey("GU") ? (Double) typeMap.get("GU") : 0D;
Double effectiveValue = Math.max(0, billValue - creditNoteValue);
dataset.addValue(effectiveValue, serviceClass + " (RE)", employee);
dataset.addValue(creditNoteValue, serviceClass + " (GU)", employee);
}
}
CategoryPlot categoryPlot = (CategoryPlot) panel.getChart().getPlot();
categoryPlot.setDataset(dataset);
categoryPlot.setDomainAxis(subCategoryAxis);
categoryPlot.setRenderer(groupedStackedBarRenderer);
int counter = 0;
for (String subCategory : subCategories) {
groupedStackedBarRenderer.setSeriesPaint(counter * 2, billPaint);
groupedStackedBarRenderer.setSeriesPaint(counter++ * 2 + 1, creditPaint);
keyToGroupMap.mapKeyToGroup(subCategory + " (RE)", subCategory);
keyToGroupMap.mapKeyToGroup(subCategory + " (GU)", subCategory);
subCategoryAxis.addSubCategory(subCategory);
}
groupedStackedBarRenderer.setSeriesToGroupMap(keyToGroupMap);
setJMenuBar(menuBar);
add(panel);
setTitle("main.title");
pack();
setVisible(true);
}
private Map<String, Map<String, Map<String, Double>>> generateRandomSet(Set<String> emplNames, Set<String> subNames) {
Random rnd = new Random();
Map<String, Map<String, Map<String, Double>>> result = new TreeMap<>();
for (String empl : emplNames) {
Map<String, Map<String, Double>> emplData = new TreeMap<>();
for (String sub : subNames) {
Map<String, Double> subData = new TreeMap<>();
subData.put("RE", rnd.nextDouble() * 1000 + 1000);
subData.put("GU", rnd.nextDouble() * 1000);
emplData.put(sub, subData);
}
result.put(empl, emplData);
}
return result;
}
}