java通过Jfreechart生成图表
pom文件引入jar包
<dependency>
<groupId>org.jfree</groupId>
<artifactId>jfreechart</artifactId>
<version>1.0.19</version>
</dependency>
<dependency>
<groupId>org.jfree</groupId>
<artifactId>org.jfree.svg</artifactId>
<version>4.0</version>
</dependency>
生成柱状图demo
package cn.bba.foundation.utils.pdf.chart;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.AxisLocation;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.labels.ItemLabelAnchor;
import org.jfree.chart.labels.ItemLabelPosition;
import org.jfree.chart.labels.StandardCategoryItemLabelGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.StandardBarPainter;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.svg.SVGGraphics2D;
import org.jfree.svg.SVGUtils;
import org.jfree.ui.TextAnchor;
import java.awt.*;
import java.io.File;
import java.io.IOException;
public class BarDemo {
public static void main(String[] args) throws IOException {
DefaultCategoryDataset dataset4 = new DefaultCategoryDataset();
dataset4.setValue(123, "", "一年级");
dataset4.setValue(222, "", "二年级");
dataset4.setValue(333, "", "三年级");
JFreeChart chart = createYBar("人数", dataset4, "/Users/Downloads/font.ttf");
SVGGraphics2D g2 = new SVGGraphics2D(1600, 1600);
Rectangle r = new Rectangle(0, 0, 1600, 1600);
chart.draw(g2, r);
File f = new File("SVGBarChartDemo1.svg");
SVGUtils.writeToSVG(f, g2.getSVGElement());
}
public static JFreeChart createYBar(String title, DefaultCategoryDataset dataset, String fontPath) {
// 创建chart,title:柱状图标题,dataset:生成数据,PlotOrientation.HORIZONTAL:柱状图旋转90度,false:不显示柱状图的label区域
JFreeChart chart = ChartFactory.createBarChart(title, "", "", dataset, PlotOrientation.HORIZONTAL, false, true, false);
// 设置柱状图标题的字体和大小
chart.setTitle(new TextTitle(title, new Font(fontPath, Font.PLAIN, 24)));
CategoryPlot plot = chart.getCategoryPlot();//获得图表区域对象
// y轴在下面或者右边显示
plot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_RIGHT);
// 柱状图背景颜色
plot.setBackgroundPaint(Color.WHITE);
// 柱状图x轴网格颜色
plot.setDomainGridlinePaint(Color.black);
// 柱状图y轴网格颜色
plot.setRangeGridlinePaint(Color.black);
//设置图表的颜色
org.jfree.chart.renderer.category.BarRenderer renderer = new org.jfree.chart.renderer.category.BarRenderer();
renderer.setSeriesPaint(0, new Color(58, 136, 231));// 设置柱子的颜色
renderer.setBarPainter(new StandardBarPainter());// 设置柱子的样式,2d
renderer.setShadowVisible(false); //不显示阴影
//显示每个柱的数值,并修改该数值的字体属性
renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator());
renderer.setBaseItemLabelsVisible(true);// 柱子上面显示数值
renderer.setBaseItemLabelPaint(Color.BLACK);// 柱子上面的数值字体颜色
renderer.setBaseItemLabelFont(new Font(fontPath, Font.PLAIN, 12));// 柱子上面的数值字体
renderer.setBasePositiveItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.OUTSIDE3, TextAnchor.CENTER));// 柱子上面数值,显示位置
renderer.setMaximumBarWidth(0.1);// 柱子最大宽度
plot.setRenderer(renderer);//使用我们设计的效果
CategoryAxis categoryAxis = plot.getDomainAxis();
categoryAxis.setTickLabelFont(new Font(fontPath, Font.PLAIN, 12));// x轴字体和大小
categoryAxis.setCategoryLabelPositions(CategoryLabelPositions.createUpRotationLabelPositions(Math.PI * 0.1));// x轴旋转角度
NumberAxis numberaxis = (NumberAxis) plot.getRangeAxis();
numberaxis.setTickLabelFont(new Font(fontPath, Font.PLAIN, 24));//y轴字体和大小
return chart;
}
}
生成结果图片:
生成饼图demo
package cn.bba.foundation.utils.pdf.chart;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.svg.SVGGraphics2D;
import org.jfree.svg.SVGUtils;
import org.jfree.ui.RectangleInsets;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.IOException;
public class PieDemo {
public static void main(String[] args) throws IOException {
DefaultPieDataset dataset1 = new DefaultPieDataset();
dataset1.setValue("一年级", 1111);
dataset1.setValue("二年级", 2222);
dataset1.setValue("三年级", 33333);
JFreeChart chart = getPieChart("人数", dataset1, "/Users/Downloads/font.ttf");
SVGGraphics2D g2 = new SVGGraphics2D(400, 400);
Rectangle r = new Rectangle(0, 0, 400, 400);
chart.draw(g2, r);
File f = new File("SVGBarChartDemo1.svg");
SVGUtils.writeToSVG(f, g2.getSVGElement());
}
public static JFreeChart getPieChart(String title, DefaultPieDataset dataset, String fontPath) {
JFreeChart chart = ChartFactory.createPieChart(title, dataset, true, false, true);
chart.setAntiAlias(false);
chart.setTitle(new TextTitle(title, new Font(fontPath, Font.PLAIN, 48)));
chart.getLegend().setItemFont(new Font(fontPath, Font.PLAIN, 35));
chart.getLegend().setItemLabelPadding(new RectangleInsets(2, 2, 2, 20));
chart.getLegend().setBorder(0, 0, 0, 0);
PiePlot plot = (PiePlot) chart.getPlot();
plot.setLabelFont(new Font(fontPath, Font.PLAIN, 16));
plot.setStartAngle(3.14f / 2f);
plot.setForegroundAlpha(0.7f);// 设置plot的前景色透明度
plot.setBackgroundAlpha(0.0f);// 设置plot的背景色透明度
// 设置标签生成器(默认{0}) {0}:key {1}:value {2}:百分比 {3}:sum
// plot.setLabelGenerator(new StandardPieSectionLabelGenerator("{0}"));
plot.setLabelGenerator(null);
plot.setOutlinePaint(null);// 去除背景边框线
plot.setLabelShadowPaint(null);
plot.setShadowGenerator(null);// 去掉阴影
plot.setShadowPaint(null);
plot.setLegendItemShape(new Rectangle2D.Double(4.0, -4.0, 40, 40));
plot.setLegendLabelGenerator(new StandardPieSectionLabelGenerator("{0}:{1}"));
setPieColor(chart);
return chart;
}
public static void setPieColor(JFreeChart chart) {
PiePlot plot = (PiePlot) chart.getPlot();
plot.setSectionPaint(0, new Color(9, 80, 162));
plot.setSectionPaint(1, new Color(82, 133, 221));
plot.setSectionPaint(2, new Color(55, 131, 166));
plot.setSectionPaint(3, new Color(86, 173, 209));
plot.setSectionPaint(4, new Color(86, 195, 248));
plot.setSectionPaint(5, new Color(97, 208, 169));
plot.setSectionPaint(6, new Color(241, 156, 82));
plot.setSectionPaint(7, new Color(246, 192, 66));
plot.setSectionPaint(8, new Color(190, 129, 222));
plot.setSectionPaint(9, new Color(87, 65, 189));
plot.setSectionPaint(10, new Color(146, 162, 189));
plot.setSectionPaint(11, new Color(173, 185, 206));
plot.setSectionPaint(12, new Color(201, 209, 222));
plot.setSectionPaint(13, new Color(228, 232, 238));
plot.setSectionPaint(14, new Color(221, 218, 210));
plot.setSectionPaint(15, new Color(0, 157, 178));
plot.setSectionPaint(16, new Color(2, 75, 81));
plot.setSectionPaint(17, new Color(7, 128, 207));
plot.setSectionPaint(18, new Color(118, 80, 5));
plot.setSectionPaint(19, new Color(213, 214, 216));
plot.setSectionPaint(20, new Color(69, 200, 220));
plot.setSectionPaint(21, new Color(133, 76, 255));
plot.setSectionPaint(22, new Color(95, 69, 255));
plot.setSectionPaint(23, new Color(71, 174, 227));
plot.setSectionPaint(24, new Color(91, 194, 231));
plot.setSectionPaint(25, new Color(105, 128, 197));
plot.setSectionPaint(26, new Color(112, 223, 223));
plot.setSectionPaint(27, new Color(247, 241, 238));
plot.setSectionPaint(28, new Color(51, 144, 255));
plot.setSectionPaint(29, new Color(150, 215, 249));
plot.setSectionPaint(30, new Color(221, 160, 221));
plot.setSectionPaint("Critical", new Color(187, 124, 141));
plot.setSectionPaint("High", new Color(231, 146, 150));
}
}
生成图片如下:
生成堆叠柱状图
package cn.bba.foundation.utils.pdf.chart;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.labels.ItemLabelAnchor;
import org.jfree.chart.labels.ItemLabelPosition;
import org.jfree.chart.labels.StandardCategoryItemLabelGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.StandardBarPainter;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.svg.SVGGraphics2D;
import org.jfree.svg.SVGUtils;
import org.jfree.ui.TextAnchor;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.IOException;
import java.text.NumberFormat;
public class StackeedBarDemo {
public static void main(String[] args) throws IOException {
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
dataset.addValue(22, "100分", "一年级");
dataset.addValue(192, "90分以上", "一年级");
dataset.addValue(132, "60分以上", "一年级");
dataset.addValue(44, "100分", "二年级");
dataset.addValue(123, "90分以上", "二年级");
dataset.addValue(241, "60分以上", "二年级");
dataset.addValue(44, "100分", "三年级");
dataset.addValue(123, "90分以上", "三年级");
dataset.addValue(431, "60分以上", "三年级");
JFreeChart chart = createStackedBar("人数", dataset, "/Users/Downloads/font.ttf");
SVGGraphics2D g2 = new SVGGraphics2D(400, 400);
Rectangle r = new Rectangle(0, 0, 400, 400);
chart.draw(g2, r);
File f = new File("SVGBarChartDemo1.svg");
SVGUtils.writeToSVG(f, g2.getSVGElement());
}
public static JFreeChart createStackedBar(String title, CategoryDataset categorydataset, String fontPath) {
JFreeChart chart = ChartFactory.createStackedBarChart(title, "", "", categorydataset, PlotOrientation.VERTICAL, true, true, false);
chart.setTitle(new TextTitle(title, new Font(fontPath, Font.PLAIN, 48)));
chart.getLegend().setItemFont(new Font(fontPath, Font.PLAIN, 30));
chart.getLegend().setBorder(0, 0, 0, 0);
CategoryPlot plot = (CategoryPlot) chart.getPlot();
plot.setDomainAxis(new MyCategoryAxis(""));
// 去除背景边框线
plot.setBackgroundPaint(Color.WHITE);
plot.setDomainGridlinePaint(Color.black);
plot.setRangeGridlinePaint(Color.black);
//柱体
MyStackedBarRenderer renderer = new MyStackedBarRenderer();
renderer.setSeriesPaint(0, new Color(7, 94, 201));//设置同一类第一个柱体颜色
renderer.setSeriesPaint(1, new Color(14, 59, 114));// 设置同一类第二个柱体颜色
renderer.setSeriesPaint(2, new Color(104, 150, 231));// 设置同一类第三个柱体颜色
renderer.setSeriesPaint(3, new Color(199, 160, 164));// 设置同一类第四个柱体颜色
renderer.setLegendShape(0, new Rectangle2D.Double(-4.0, -4.0, 50, 30));
renderer.setLegendShape(1, new Rectangle2D.Double(-4.0, -4.0, 50, 30));
renderer.setLegendShape(2, new Rectangle2D.Double(-4.0, -4.0, 50, 30));
renderer.setLegendShape(3, new Rectangle2D.Double(-4.0, -4.0, 50, 30));
renderer.setMaximumBarWidth(0.1);
//柱体标签是否可见
renderer.setBaseItemLabelsVisible(true);
renderer.setBaseItemLabelPaint(Color.BLACK);
renderer.setBaseItemLabelFont(new Font(fontPath, Font.PLAIN, 24));
renderer.setBasePositiveItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.OUTSIDE12, TextAnchor.CENTER));
renderer.setBaseNegativeItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.OUTSIDE12, TextAnchor.TOP_CENTER));
//设置柱体标签值的格式
renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator("{2}", NumberFormat.getNumberInstance()));
renderer.setBarPainter(new StandardBarPainter());
renderer.setShadowVisible(false); //不显示阴影
plot.setRenderer(renderer);
CategoryAxis categoryAxis = plot.getDomainAxis();
categoryAxis.setTickLabelFont(new Font(fontPath, Font.PLAIN, 24));
NumberAxis numberaxis = (NumberAxis) plot.getRangeAxis();
numberaxis.setTickLabelFont(new Font(fontPath, Font.PLAIN, 24));
return chart;
}
}
package cn.bba.foundation.utils.pdf.chart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.entity.EntityCollection;
import org.jfree.chart.labels.CategoryItemLabelGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.CategoryItemRendererState;
import org.jfree.chart.renderer.category.StackedBarRenderer;
import org.jfree.data.DataUtilities;
import org.jfree.data.category.CategoryDataset;
import org.jfree.ui.RectangleEdge;
import java.awt.*;
import java.awt.geom.Rectangle2D;
public class MyStackedBarRenderer extends StackedBarRenderer {
private final boolean renderAsPercentages = false;
public void drawItem(Graphics2D g2, CategoryItemRendererState state,
Rectangle2D dataArea, CategoryPlot plot, CategoryAxis domainAxis,
ValueAxis rangeAxis, CategoryDataset dataset, int row,
int column, int pass) {
if (!isSeriesVisible(row)) {
return;
}
// nothing is drawn for null values...
Number dataValue = dataset.getValue(row, column);
if (dataValue == null) {
return;
}
double value = dataValue.doubleValue();
double total = 0.0; // only needed if calculating percentages
if (this.renderAsPercentages) {
total = DataUtilities.calculateColumnTotal(dataset, column,
state.getVisibleSeriesArray());
value = value / total;
}
PlotOrientation orientation = plot.getOrientation();
double barW0 = domainAxis.getCategoryMiddle(column, getColumnCount(),
dataArea, plot.getDomainAxisEdge())
- state.getBarWidth() / 2.0;
double positiveBase = getBase();
double negativeBase = positiveBase;
for (int i = 0; i < row; i++) {
Number v = dataset.getValue(i, column);
if (v != null && isSeriesVisible(i)) {
double d = v.doubleValue();
if (this.renderAsPercentages) {
d = d / total;
}
if (d > 0) {
positiveBase = positiveBase + d;
} else {
negativeBase = negativeBase + d;
}
}
}
double translatedBase;
double translatedValue;
boolean positive = (value > 0.0);
boolean inverted = rangeAxis.isInverted();
RectangleEdge barBase;
if (orientation == PlotOrientation.HORIZONTAL) {
if (positive && inverted || !positive && !inverted) {
barBase = RectangleEdge.RIGHT;
} else {
barBase = RectangleEdge.LEFT;
}
} else {
if (positive && !inverted || !positive && inverted) {
barBase = RectangleEdge.BOTTOM;
} else {
barBase = RectangleEdge.TOP;
}
}
RectangleEdge location = plot.getRangeAxisEdge();
if (positive) {
translatedBase = rangeAxis.valueToJava2D(positiveBase, dataArea,
location);
translatedValue = rangeAxis.valueToJava2D(positiveBase + value,
dataArea, location);
} else {
translatedBase = rangeAxis.valueToJava2D(negativeBase, dataArea,
location);
translatedValue = rangeAxis.valueToJava2D(negativeBase + value,
dataArea, location);
}
double barL0 = Math.min(translatedBase, translatedValue);
double barLength = Math.max(Math.abs(translatedValue - translatedBase),
getMinimumBarLength());
Rectangle2D bar;
if (orientation == PlotOrientation.HORIZONTAL) {
bar = new Rectangle2D.Double(barL0, barW0, barLength,
state.getBarWidth());
} else {
if (column % 2 == 0) {
bar = new Rectangle2D.Double(barW0, barL0, state.getBarWidth(),
barLength);
} else {
bar = new Rectangle2D.Double(barW0 - (state.getBarWidth() / 4), barL0, state.getBarWidth(),
barLength);
}
}
if (pass == 0) {
if (getShadowsVisible()) {
boolean pegToBase = (positive && (positiveBase == getBase()))
|| (!positive && (negativeBase == getBase()));
getBarPainter().paintBarShadow(g2, this, row, column, bar,
barBase, false);
}
} else if (pass == 1) {
getBarPainter().paintBar(g2, this, row, column, bar, barBase);
// add an item entity, if this information is being collected
EntityCollection entities = state.getEntityCollection();
if (entities != null) {
addItemEntity(entities, dataset, row, column, bar);
}
} else if (pass == 2) {
CategoryItemLabelGenerator generator = getItemLabelGenerator(row,
column);
if (generator != null && isItemLabelVisible(row, column)) {
drawItemLabel(g2, dataset, row, column, plot, generator, bar,
(value < 0.0));
}
}
}
}
package cn.bba.foundation.utils.pdf.chart;
import org.jfree.chart.axis.*;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.text.TextBlock;
import org.jfree.ui.RectangleEdge;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
public class MyCategoryAxis extends CategoryAxis {
private final CategoryLabelPositions categoryLabelPositions = CategoryLabelPositions.STANDARD;
private final float maximumCategoryLabelWidthRatio = 0.0f;
public MyCategoryAxis(String category) {
super(category);
}
public List<Tick> refreshTicks(Graphics2D g2, AxisState state, Rectangle2D dataArea, RectangleEdge edge) {
List<Tick> ticks = new ArrayList<>();
// sanity check for data area...
if (dataArea.getHeight() <= 0.0 || dataArea.getWidth() < 0.0) {
return ticks;
}
CategoryPlot plot = (CategoryPlot) getPlot();
List<Object> categories = plot.getCategoriesForAxis(this);
categories = categories.stream().filter(e -> !e.toString().contains(" ")).collect(Collectors.toList());
double max = 0.0;
if (categories != null) {
CategoryLabelPosition position
= this.categoryLabelPositions.getLabelPosition(edge);
float r = this.maximumCategoryLabelWidthRatio;
if (r <= 0.0) {
r = position.getWidthRatio();
}
float l;
if (position.getWidthType() == CategoryLabelWidthType.CATEGORY) {
l = (float) calculateCategorySize(categories.size(), dataArea,
edge);
} else {
if (RectangleEdge.isLeftOrRight(edge)) {
l = (float) dataArea.getWidth();
} else {
l = (float) dataArea.getHeight();
}
}
int categoryIndex = 0;
Iterator iterator = categories.iterator();
while (iterator.hasNext()) {
Comparable category = (Comparable) iterator.next();
g2.setFont(getTickLabelFont(category));
TextBlock label = createLabel(category, l * r, edge, g2);
if (edge == RectangleEdge.TOP || edge == RectangleEdge.BOTTOM) {
max = Math.max(max, calculateTextBlockHeight(label,
position, g2));
} else if (edge == RectangleEdge.LEFT
|| edge == RectangleEdge.RIGHT) {
max = Math.max(max, calculateTextBlockWidth(label,
position, g2));
}
Tick tick = new CategoryTick(category, label,
position.getLabelAnchor(),
position.getRotationAnchor(), position.getAngle());
ticks.add(tick);
categoryIndex = categoryIndex + 1;
}
}
state.setMax(max);
return ticks;
}
}
生成图片: