JAVA jfreechart生成柱状图

news2024/12/23 5:45:45

JAVA jfreechart生成柱状图

在项目资源评估中,也就是生成word文档里需要根据数据生成柱状图,在网上找到了jfreechart工具包,来生成柱状图,当然他不仅仅只能生成柱状图,还支持折线图、饼状图等等…

过程

导入依赖

        <dependency>
            <groupId>org.jfree</groupId>
            <artifactId>jfreechart</artifactId>
<!--            <version>1.5.3</version>-->
            <version>1.0.19</version>
        </dependency>

注:1.5.3与1.0.19版本api变化比较大,由于工具类内容copy其他文章,并且测试发现是1.0.19,所以这里引入此版本

封装

主要有两个类SerieChartUtils

Serie:可以理解为图中的数据对象,name是数据的名称,data是数据集合

package com.hxkj.server.photovolatic.api.core.chart;

import java.io.Serializable;
import java.util.Vector;

/**
 * @author zsl0
 * created on 2023/7/6 17:51
 */
public class Serie implements Serializable {

    private static final long serialVersionUID = 1L;
    private String name;// 名字
    private Vector<Object> data;// 数据值

    public Serie() {

    }

    /**
     *
     * @param name
     *            名称(线条名称)
     * @param data
     *            数据(线条上的所有数据值)
     */
    public Serie(String name, Vector<Object> data) {

        this.name = name;
        this.data = data;
    }

    /**
     *
     * @param name
     *            名称(线条名称)
     * @param array
     *            数据(线条上的所有数据值)
     */
    public Serie(String name, Object[] array) {
        this.name = name;
        if (array != null) {
            data = new Vector<Object>(array.length);
            for (int i = 0; i < array.length; i++) {
                data.add(array[i]);
            }
        }
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Vector<Object> getData() {
        return data;
    }

    public void setData(Vector<Object> data) {
        this.data = data;
    }

}

ChartUtils工具类:这里根据原来的工具封装了createDefaultBarPngBase64()方法,因为这里是应用到word中做展示,所以直接传入数据参数,生成转Base64后的png字符串;(这个类可以根据自己实际需求再封装成自己的实现)

package com.hxkj.server.photovolatic.api.core.chart;

import lombok.extern.slf4j.Slf4j;
import org.jfree.chart.*;
import org.jfree.chart.axis.*;
import org.jfree.chart.block.BlockBorder;
import org.jfree.chart.labels.*;
import org.jfree.chart.plot.*;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.chart.renderer.category.StackedBarRenderer;
import org.jfree.chart.renderer.category.StandardBarPainter;
import org.jfree.chart.renderer.xy.StandardXYBarPainter;
import org.jfree.chart.renderer.xy.XYBarRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.time.Day;
import org.jfree.data.time.TimeSeries;
import org.jfree.ui.RectangleInsets;
import org.jfree.ui.TextAnchor;

import java.awt.*;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Base64;
import java.util.Date;
import java.util.Vector;

/**
 * Jfreechart工具类
 * <p>
 * 解决中午乱码问题<br>
 * 用来创建类别图表数据集、创建饼图数据集、时间序列图数据集<br>
 * 用来对柱状图、折线图、饼图、堆积柱状图、时间序列图的样式进行渲染<br>
 * 设置X-Y坐标轴样式
 * <p>
 *
 *
 * @author chenchangwen
 * @since:2014-2-18
 *
 */
@Slf4j
public class ChartUtils {
    private static String NO_DATA_MSG = "数据加载失败";
    private static Font FONT = new Font("宋体", Font.PLAIN, 12);
    public static Color[] CHART_COLORS = {
            new Color(31,129,188), new Color(92,92,97), new Color(144,237,125), new Color(255,188,117),
            new Color(153,158,255), new Color(255,117,153), new Color(253,236,109), new Color(128,133,232),
            new Color(158,90,102),new Color(255, 204, 102) };// 颜色

    static {
        setChartTheme();
    }

    public ChartUtils() {
    }

    /**
     * 中文主题样式 解决乱码
     */
    private static void setChartTheme() {
        // 设置中文主题样式 解决乱码
        StandardChartTheme chartTheme = new StandardChartTheme("CN");
        // 设置标题字体
        chartTheme.setExtraLargeFont(FONT);
        // 设置图例的字体
        chartTheme.setRegularFont(FONT);
        // 设置轴向的字体
        chartTheme.setLargeFont(FONT);
        chartTheme.setSmallFont(FONT);
        chartTheme.setTitlePaint(new Color(51, 51, 51));
        chartTheme.setSubtitlePaint(new Color(85, 85, 85));

        chartTheme.setLegendBackgroundPaint(Color.WHITE);// 设置标注
        chartTheme.setLegendItemPaint(Color.BLACK);//
        chartTheme.setChartBackgroundPaint(Color.WHITE);
        // 绘制颜色绘制颜色.轮廓供应商
        // paintSequence,outlinePaintSequence,strokeSequence,outlineStrokeSequence,shapeSequence

        Paint[] OUTLINE_PAINT_SEQUENCE = new Paint[] { Color.WHITE };
        // 绘制器颜色源
        DefaultDrawingSupplier drawingSupplier = new DefaultDrawingSupplier(CHART_COLORS, CHART_COLORS, OUTLINE_PAINT_SEQUENCE,
                DefaultDrawingSupplier.DEFAULT_STROKE_SEQUENCE, DefaultDrawingSupplier.DEFAULT_OUTLINE_STROKE_SEQUENCE,
                DefaultDrawingSupplier.DEFAULT_SHAPE_SEQUENCE);
        chartTheme.setDrawingSupplier(drawingSupplier);

        chartTheme.setPlotBackgroundPaint(Color.WHITE);// 绘制区域
        chartTheme.setPlotOutlinePaint(Color.WHITE);// 绘制区域外边框
        chartTheme.setLabelLinkPaint(new Color(8, 55, 114));// 链接标签颜色
        chartTheme.setLabelLinkStyle(PieLabelLinkStyle.CUBIC_CURVE);

        chartTheme.setAxisOffset(new RectangleInsets(5, 12, 5, 12));
        chartTheme.setDomainGridlinePaint(new Color(192, 208, 224));// X坐标轴垂直网格颜色
        chartTheme.setRangeGridlinePaint(new Color(192, 192, 192));// Y坐标轴水平网格颜色

        chartTheme.setBaselinePaint(Color.WHITE);
        chartTheme.setCrosshairPaint(Color.BLUE);// 不确定含义
        chartTheme.setAxisLabelPaint(new Color(51, 51, 51));// 坐标轴标题文字颜色
        chartTheme.setTickLabelPaint(new Color(67, 67, 72));// 刻度数字
        chartTheme.setBarPainter(new StandardBarPainter());// 设置柱状图渲染
        chartTheme.setXYBarPainter(new StandardXYBarPainter());// XYBar 渲染

        chartTheme.setItemLabelPaint(Color.black);
        chartTheme.setThermometerPaint(Color.white);// 温度计

        ChartFactory.setChartTheme(chartTheme);
    }

    /**
     * 必须设置文本抗锯齿
     */
    private static void setAntiAlias(JFreeChart chart) {
        chart.setTextAntiAlias(false);

    }

    /**
     * 设置图例无边框,默认黑色边框
     */
    private static void setLegendEmptyBorder(JFreeChart chart) {
        chart.getLegend().setFrame(new BlockBorder(Color.WHITE));

    }

    /**
     * 创建类别数据集合
     */
    private static DefaultCategoryDataset createDefaultCategoryDataset(Vector<Serie> series, String[] categories) {
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();

        for (Serie serie : series) {
            String name = serie.getName();
            Vector<Object> data = serie.getData();
            if (data != null && categories != null && data.size() == categories.length) {
                for (int index = 0; index < data.size(); index++) {
                    String value = data.get(index) == null ? "" : data.get(index).toString();
                    if (isPercent(value)) {
                        value = value.substring(0, value.length() - 1);
                    }
                    if (isNumber(value)) {
                        dataset.setValue(Double.parseDouble(value), name, categories[index]);
                    }
                }
            }

        }
        return dataset;

    }

    /**
     * 创建饼图数据集合
     */
    private static DefaultPieDataset createDefaultPieDataset(String[] categories, Object[] datas) {
        DefaultPieDataset dataset = new DefaultPieDataset();
        for (int i = 0; i < categories.length && categories != null; i++) {
            String value = datas[i].toString();
            if (isPercent(value)) {
                value = value.substring(0, value.length() - 1);
            }
            if (isNumber(value)) {
                dataset.setValue(categories[i], Double.valueOf(value));
            }
        }
        return dataset;

    }

    /**
     * 创建时间序列数据
     *
     * @param category
     *            类别
     * @param dateValues
     *            日期-值 数组
     * @return
     */
    private static TimeSeries createTimeseries(String category, Vector<Object[]> dateValues) {
        TimeSeries timeseries = new TimeSeries(category);

        if (dateValues != null) {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            for (Object[] objects : dateValues) {
                Date date = null;
                try {
                    date = dateFormat.parse(objects[0].toString());
                } catch (ParseException e) {
                }
                String sValue = objects[1].toString();
                double dValue = 0;
                if (date != null && isNumber(sValue)) {
                    dValue = Double.parseDouble(sValue);
                    timeseries.add(new Day(date), dValue);
                }
            }
        }

        return timeseries;
    }

    /**
     * 设置 折线图样式
     *
     * @param plot 绘图
     * @param isShowDataLabels
     *            是否显示数据标签 默认不显示节点形状
     */
    private static void setLineRender(CategoryPlot plot, boolean isShowDataLabels) {
        setLineRender(plot, isShowDataLabels, false);
    }

    /**
     * 设置折线图样式
     *
     * @param plot 绘图
     * @param isShowDataLabels
     *            是否显示数据标签
     */
    private static void setLineRender(CategoryPlot plot, boolean isShowDataLabels, boolean isShapesVisible) {
        plot.setNoDataMessage(NO_DATA_MSG);
        plot.setInsets(new RectangleInsets(10, 10, 0, 10), false);
        LineAndShapeRenderer renderer = (LineAndShapeRenderer) plot.getRenderer();

        renderer.setStroke(new BasicStroke(1.5F));
        if (isShowDataLabels) {
            renderer.setBaseItemLabelsVisible(true);
            renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator(StandardCategoryItemLabelGenerator.DEFAULT_LABEL_FORMAT_STRING,
                    NumberFormat.getInstance()));
            renderer.setBasePositiveItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.OUTSIDE1, TextAnchor.BOTTOM_CENTER));// weizhi
        }
        renderer.setBaseShapesVisible(isShapesVisible);// 数据点绘制形状
        setXAixs(plot);
        setYAixs(plot);

    }

    /**
     * 设置时间序列图样式
     *
     * @param plot 绘图
     * @param isShowData
     *            是否显示数据
     * @param isShapesVisible
     *            是否显示数据节点形状
     */
    private static void setTimeSeriesRender(Plot plot, boolean isShowData, boolean isShapesVisible) {

        XYPlot xyplot = (XYPlot) plot;
        xyplot.setNoDataMessage(NO_DATA_MSG);
        xyplot.setInsets(new RectangleInsets(10, 10, 5, 10));

        XYLineAndShapeRenderer xyRenderer = (XYLineAndShapeRenderer) xyplot.getRenderer();

        xyRenderer.setBaseItemLabelGenerator(new StandardXYItemLabelGenerator());
        xyRenderer.setBaseShapesVisible(false);
        if (isShowData) {
            xyRenderer.setBaseItemLabelsVisible(true);
            xyRenderer.setBaseItemLabelGenerator(new StandardXYItemLabelGenerator());
            xyRenderer.setBasePositiveItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.OUTSIDE1, TextAnchor.BOTTOM_CENTER));// weizhi
        }
        xyRenderer.setBaseShapesVisible(isShapesVisible);// 数据点绘制形状

        DateAxis domainAxis = (DateAxis) xyplot.getDomainAxis();
        domainAxis.setAutoTickUnitSelection(false);
        DateTickUnit dateTickUnit = new DateTickUnit(DateTickUnitType.YEAR, 1, new SimpleDateFormat("yyyy-MM")); // 第二个参数是时间轴间距
        domainAxis.setTickUnit(dateTickUnit);

        StandardXYToolTipGenerator xyTooltipGenerator = new StandardXYToolTipGenerator("{1}:{2}", new SimpleDateFormat("yyyy-MM-dd"), new DecimalFormat("0"));
        xyRenderer.setBaseToolTipGenerator(xyTooltipGenerator);

        setXY_XAixs(xyplot);
        setXY_YAixs(xyplot);

    }

    /**
     * 设置时间序列图样式 -默认不显示数据节点形状
     *
     * @param plot 绘图
     * @param isShowData
     *            是否显示数据
     */

    private static void setTimeSeriesRender(Plot plot, boolean isShowData) {
        setTimeSeriesRender(plot, isShowData, false);
    }

    /**
     * 设置时间序列图渲染:但是存在一个问题:如果timeseries里面的日期是按照天组织, 那么柱子的宽度会非常小,和直线一样粗细
     *
     * @param plot 绘图
     * @param isShowDataLabels
     */

    private static void setTimeSeriesBarRender(Plot plot, boolean isShowDataLabels) {

        XYPlot xyplot = (XYPlot) plot;
        xyplot.setNoDataMessage(NO_DATA_MSG);

        XYBarRenderer xyRenderer = new XYBarRenderer(0.1D);
        xyRenderer.setBaseItemLabelGenerator(new StandardXYItemLabelGenerator());

        if (isShowDataLabels) {
            xyRenderer.setBaseItemLabelsVisible(true);
            xyRenderer.setBaseItemLabelGenerator(new StandardXYItemLabelGenerator());
        }

        StandardXYToolTipGenerator xyTooltipGenerator = new StandardXYToolTipGenerator("{1}:{2}", new SimpleDateFormat("yyyy-MM-dd"), new DecimalFormat("0"));
        xyRenderer.setBaseToolTipGenerator(xyTooltipGenerator);
        setXY_XAixs(xyplot);
        setXY_YAixs(xyplot);

    }

    /**
     * 设置柱状图渲染
     *
     * @param plot 绘图
     * @param isShowDataLabels
     */
    private static void setBarRenderer(CategoryPlot plot, boolean isShowDataLabels) {

        plot.setNoDataMessage(NO_DATA_MSG);
        plot.setInsets(new RectangleInsets(10, 20, 5, 20));

        // 设置柱状图样式
        BarRenderer renderer = (BarRenderer) plot.getRenderer();
        renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator());
        renderer.setMaximumBarWidth(0.075);// 设置柱子最大宽度
        renderer.setItemMargin(0.1);
        for (int i = 0; i < CHART_COLORS.length; i++) {
            // 设置柱子颜色
            renderer.setSeriesPaint(i, CHART_COLORS[i]);
        }

        renderer.setShadowVisible(false); // 去除阴影效果

        // 设置轴样式
        CategoryAxis domainAxis = plot.getDomainAxis();
        domainAxis.setTickLabelFont(new Font("宋体", Font.PLAIN, 12)); // 设置X轴上提示文字样式
        domainAxis.setLabelFont(new Font("宋体", Font.BOLD, 14)); // 设置X轴下的标签文字
//        domainAxis.setTickMarksVisible(false);  // 坐标轴标尺不显示
        domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45);

        NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
        rangeAxis.setTickLabelFont(new Font("宋体", Font.PLAIN, 12));  // 设置Y轴的提示文字样式
        rangeAxis.setLabelFont(new Font("宋体", Font.BOLD, 14));
//        rangeAxis.setLowerMargin(0.35); // 设置最低的一个 Item 与图片底端的距离
//        rangeAxis.setUpperMargin(0.45); // 设置最高的一个 Item 与图片顶端的距离
//        rangeAxis.setUpperBound(8000.0);  // 设置Y轴的最大值


        if (isShowDataLabels) {
            renderer.setBaseItemLabelsVisible(true);
        }

        setXAixs(plot);
        setYAixs(plot);
    }

    /**
     * 设置堆积柱状图渲染
     *
     * @param plot 绘图
     */

    private static void setStackBarRender(CategoryPlot plot) {
        plot.setNoDataMessage(NO_DATA_MSG);
        plot.setInsets(new RectangleInsets(10, 10, 5, 10));
        StackedBarRenderer renderer = (StackedBarRenderer) plot.getRenderer();
        renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator());
        plot.setRenderer(renderer);
        setXAixs(plot);
        setYAixs(plot);
    }

    /**
     * 设置类别图表(CategoryPlot) X坐标轴线条颜色和样式
     *
     * @param plot 绘图
     */
    private static void setXAixs(CategoryPlot plot) {
        Color lineColor = new Color(31, 121, 170);
        plot.getDomainAxis().setAxisLinePaint(lineColor);// X坐标轴颜色
        plot.getDomainAxis().setTickMarkPaint(lineColor);// X坐标轴标记|竖线颜色

    }

    /**
     * 设置类别图表(CategoryPlot) Y坐标轴线条颜色和样式 同时防止数据无法显示
     *
     * @param plot 绘图
     */
    private static void setYAixs(CategoryPlot plot) {
        Color lineColor = new Color(192, 208, 224);
        ValueAxis axis = plot.getRangeAxis();
        axis.setAxisLinePaint(lineColor);// Y坐标轴颜色
        axis.setTickMarkPaint(lineColor);// Y坐标轴标记|竖线颜色
        // 隐藏Y刻度
        axis.setAxisLineVisible(false);
        axis.setTickMarksVisible(false);
        // Y轴网格线条
        plot.setRangeGridlinePaint(new Color(192, 192, 192));
        plot.setRangeGridlineStroke(new BasicStroke(1));

        plot.getRangeAxis().setUpperMargin(0.1);// 设置顶部Y坐标轴间距,防止数据无法显示
        plot.getRangeAxis().setLowerMargin(0.1);// 设置底部Y坐标轴间距

    }

    /**
     * 设置XY图表(XYPlot) X坐标轴线条颜色和样式
     *
     * @param plot 绘图
     */
    private static void setXY_XAixs(XYPlot plot) {
        Color lineColor = new Color(31, 121, 170);
        plot.getDomainAxis().setAxisLinePaint(lineColor);// X坐标轴颜色
        plot.getDomainAxis().setTickMarkPaint(lineColor);// X坐标轴标记|竖线颜色

    }

    /**
     * 设置XY图表(XYPlot) Y坐标轴线条颜色和样式 同时防止数据无法显示
     *
     * @param plot 绘图
     */
    private static void setXY_YAixs(XYPlot plot) {
        Color lineColor = new Color(192, 208, 224);
        ValueAxis axis = plot.getRangeAxis();
        axis.setAxisLinePaint(lineColor);// X坐标轴颜色
        axis.setTickMarkPaint(lineColor);// X坐标轴标记|竖线颜色
        // 隐藏Y刻度
        axis.setAxisLineVisible(false);
        axis.setTickMarksVisible(false);
        // Y轴网格线条
        plot.setRangeGridlinePaint(new Color(192, 192, 192));
        plot.setRangeGridlineStroke(new BasicStroke(1));
        plot.setDomainGridlinesVisible(false);

        plot.getRangeAxis().setUpperMargin(0.12);// 设置顶部Y坐标轴间距,防止数据无法显示
        plot.getRangeAxis().setLowerMargin(0.12);// 设置底部Y坐标轴间距

    }

    /**
     * 设置饼状图渲染
     */
    private static void setPieRender(Plot plot) {

        plot.setNoDataMessage(NO_DATA_MSG);
        plot.setInsets(new RectangleInsets(10, 10, 5, 10));
        PiePlot piePlot = (PiePlot) plot;
        piePlot.setInsets(new RectangleInsets(0, 0, 0, 0));
        piePlot.setCircular(true);// 圆形

        // piePlot.setSimpleLabels(true);// 简单标签
        piePlot.setLabelGap(0.01);
        piePlot.setInteriorGap(0.05D);
        piePlot.setLegendItemShape(new Rectangle(10, 10));// 图例形状
        piePlot.setIgnoreNullValues(true);
        piePlot.setLabelBackgroundPaint(null);// 去掉背景色
        piePlot.setLabelShadowPaint(null);// 去掉阴影
        piePlot.setLabelOutlinePaint(null);// 去掉边框
        piePlot.setShadowPaint(null);
        // 0:category 1:value:2 :percentage
        piePlot.setLabelGenerator(new StandardPieSectionLabelGenerator("{0}:{2}"));// 显示标签数据
    }

    /**
     * 是不是一个%形式的百分比
     *
     * @param str
     * @return
     */
    private static boolean isPercent(String str) {
        return str != null ? str.endsWith("%") && isNumber(str.substring(0, str.length() - 1)) : false;
    }

    /**
     * 是不是一个数字
     *
     * @param str
     * @return
     */
    private static boolean isNumber(String str) {
        return str != null ? str.matches("^[-+]?(([0-9]+)((([.]{0})([0-9]*))|(([.]{1})([0-9]+))))$") : false;
    }

    // ===================================== 根据原工具封装 =====================================

    /**
     * 创建柱状图png(Base64)
     * @param series 数据集合(每条曲线)
     * @param categories 类别(名称)
     * @return 柱状图png,Base64后字符串
     */
    public static String createDefaultBarPngBase64(Vector<Serie> series, String[] categories) {
        String result = null;

        // 创建数据集
        DefaultCategoryDataset dataset = ChartUtils.createDefaultCategoryDataset(series, categories);

        // 创建柱状图
        JFreeChart chart = ChartFactory.createBarChart(
                "",     // 图表标题
                "",              // X轴标题
                "",                 // Y轴标题
                dataset,                 // 数据集
                PlotOrientation.VERTICAL,// 图表方向 VERTICAL垂直 HORIZONTAL水平
                true,                    // 是否显示图例
                true,                    // 是否生成工具提示
                false                    // 是否生成URL链接
        );

        setLegendEmptyBorder(chart);

        // 对柱状图进行样式渲染
        CategoryPlot plot = chart.getCategoryPlot();
        ChartUtils.setBarRenderer(plot, true);

        // 保存为png-Base64
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ChartUtilities.writeChartAsPNG(baos, chart, 600, 400);
            byte[] imageByte = Base64.getEncoder().encode(baos.toByteArray());
            //        System.out.println("data:image/png;base64," + new String(imageByte));
            result = new String(imageByte);
        } catch (IOException e) {
            e.printStackTrace();
            log.error("生成柱状图失败!");
        }

        return result;
    }

    public static void main(String[] args) {
        // 创建数据系列
        Serie serie1 = new Serie("总曝辐量", new Vector<>(Arrays.asList(5721.32, 5544.72, 5754.28, 5654.42, 5453.31, 5721.32, 5544.72, 5754.28, 5654.42, 5453.31, 5721.32, 5544.72)));
        Serie serie2 = new Serie("直接曝辐量1", new Vector<>(Arrays.asList(3721.32, 3544.72, 3754.28, 3654.42, 3453.31, 3721.32, 3544.72, 3754.28, 3654.42, 3453.31, 3721.32, 3544.72)));
//        Serie serie3 = new Serie("直接曝辐量2", new Vector<>(Arrays.asList(3721.32, 3544.72, 3754.28, 3654.42, 3453.31)));
//        Serie serie4 = new Serie("直接曝辐量3", new Vector<>(Arrays.asList(3721.32, 3544.72, 3754.28, 3654.42, 3453.31)));
//        Serie serie5 = new Serie("直接曝辐量4", new Vector<>(Arrays.asList(3721.32, 3544.72, 3754.28, 3654.42, 3453.31)));

        // 创建数据集
        DefaultCategoryDataset dataset = ChartUtils.createDefaultCategoryDataset(new Vector<>(Arrays.asList(serie1, serie2)), new String[]{"一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"});
//        DefaultCategoryDataset dataset = ChartUtils.createDefaultCategoryDataset(new Vector<>(Arrays.asList(serie1, serie2 ,serie3 ,serie4 ,serie5)), new String[]{"2018年", "2019年", "2020年", "2021年", "2022年"});

        // 创建堆积柱状图
        // 创建柱状图
        JFreeChart chart = ChartFactory.createBarChart(
                "",     // 图表标题
                "",              // X轴标题
                "",                 // Y轴标题
                dataset,                 // 数据集
                PlotOrientation.VERTICAL,// 图表方向
//                PlotOrientation.HORIZONTAL,// 图表方向
                true,                    // 是否显示图例
                true,                    // 是否生成工具提示
                false                    // 是否生成URL链接
        );

        chart.getLegend().setFrame(new BlockBorder(Color.WHITE));

        // 对柱状图进行样式渲染
        CategoryPlot plot = chart.getCategoryPlot();
        ChartUtils.setBarRenderer(plot, true);
//        setXAixs(plot);
//        setYAixs(plot);

//        // 显示图表
//        ChartFrame frame = new ChartFrame("Bar Chart", chart);
//        frame.pack();
//        frame.setVisible(true);

        try {
            ChartUtilities.saveChartAsPNG(new File("abc.png"), chart, 600, 400);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ChartUtilities.writeChartAsPNG(baos, chart, 600, 400);
            byte[] imageByte = Base64.getEncoder().encode(baos.toByteArray());
            System.out.println("data:image/png;base64," + new String(imageByte));
        } catch (IOException e) {
            e.getMessage();
        }
    }


}

ChartUtils类中main方法的案例,生成图片为,可以根据图和代码梳理下怎么使用jfreechart

请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/727978.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

快速创建剪映草稿

实现原理 : JianYingPro 项目文件是 json 的形式存储的,只需要创建draft_content.json,draft_mate_info.json 打开软件后会自动补全。添加一个媒体到轨道顺序 草稿媒体库 -> 内容媒体库-> 轨道片段add_media_to_track 会识别媒体类型,加入到对应轨道。当没有视频轨道时…

哈希表 基础理论

什么是哈希表&#xff1f; 哈希表英文名hash table&#xff0c;国内有一些书籍也翻译为散列表。哈希表是根据关键码的值而直接进行访问的数据结构。 直白来讲&#xff0c;其实数组就是一张哈希表&#xff0c;哈希表中关键码就是数组的索引下标&#xff0c;然后通过下标直接访…

华为云编译构建CodeArts Build新手操作指南

华为云编译构建&#xff08;CodeArts Build&#xff09;基于云端大规模并发加速&#xff0c;为客户提供高速、低成本、配置简单的混合语言构建能力&#xff0c;帮助客户缩短构建时间&#xff0c;提升构建效率。 本文将给各位开发者带来华为云CodeArts Pipeline的手把手初级教学…

亚马逊买家账号被封的原因

亚马逊封号原因有很多种情况&#xff0c;以下是一些可能导致账号被封的常见原因&#xff1a; 1、违反亚马逊的服务条款&#xff1a;亚马逊有一系列的服务条款和规定&#xff0c;如果您违反了这些规定&#xff0c;比如多次提交虚假评价、涉及欺诈行为、滥用退货政策等&#xff…

【深度学习】日常笔记9

泛化误差&#xff08;generalization error&#xff09;是指&#xff0c;模型应⽤在同样从原始样本的分布中 抽取的⽆限多数据样本时&#xff0c;模型误差的期望。考虑对掷硬币的结果&#xff08;类别0&#xff1a;正⾯&#xff0c;类别1&#xff1a;反⾯&#xff09;进⾏分类的…

AIGC - Stable Diffusion 图像控制插件 ControlNet (OpenPose) 配置与使用

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/131591887 论文&#xff1a;Adding Conditional Control to Text-to-Image Diffusion Models ControlNet 是神经网络结构&#xff0c;用于控制预…

CentOS7安装详细安装

CentOS 7镜像下载 官网下载链接&#xff1a;http://isoredirect.centos.org/centos/7/isos/x86_64/ step1: 进入下载页&#xff0c;选择阿里云站点进行下载 Actual Country 国内资源 Nearby Countries 周边国家资源 阿里云站点&#xff1a;http://mirrors.aliyun.com/cento…

开源微服务框架是什么?看完这篇文章就知道了

随着低代码开发平台的快速发展&#xff0c;企业实现流程化管理的愿望指日可待。开源微服务框架是什么&#xff1f;都有哪些特点和优势&#xff1f;作为企业&#xff0c;想要提高办公协作效率&#xff0c;做好数据管理&#xff0c;应用专用的开发平台可以少走弯路&#xff0c;创…

【电子量产工具】6. 业务系统

文章目录 前言一、业务系统分析二、处理配置文件三、生成界面四、根据输入事件找到按钮五、业务系统总流程测试测试效果&#xff1a;总结 前言 最近看了 电子量产工具 这个项目&#xff0c;本专栏是对该项目的一个总结。 一、业务系统分析 前面实现了各个子系统&#xff1a;显…

【Java项目】Vue+ElementUI+Ceph实现多类型文件上传功能并实现文件预览功能

文章目录 效果演示前端后端Java 效果演示 先说一下我们的需求&#xff0c;我们的需求就是文件上传&#xff0c;之前的接口是只支持上传图片的&#xff0c;之后需求是需要支持上传pdf&#xff0c;所以我就得换接口&#xff0c;把原先图片上传的接口换为后端ceph&#xff0c;但是…

MV-Map论文研读

MV-Map MV-Map: Offboard HD-Map Generation with Multi-view Consistency 论文&#xff1a;https://arxiv.org/pdf/2305.08851.pdf code&#xff1a;https://github.com/ZiYang-xie/MV-Map 代码未开源 总体网络结构 简述 论文首次提出以非车载的方式产生高精度地图。可以…

基于QT使用7z压缩与解压总结

1. 概述 本文主要讲述使用7z第三方工具对文件或文件夹进行加密压缩和解密解压相关方法。7z的全称7-Zip&#xff0c;是一款开源软件。&#xff08;资源主页&#xff1a;https://7-zip.org/&#xff09;2. 设计原理 本文主要使用7z.exe通过命令行来实现压缩与解压功能&…

数据库之MySQL字符集与数据库操作

目录 字符集 CHRARCTER SET 与COLLATION的关联 CHRARCTER SET 定义 基础操作 查看当前MySQL Server支持的 CHARACTER SET 查看特定字符集信息&#xff08;主要包含默认的COLLATION 与 MAXLEN&#xff09; COLLATION 定义 COLLATION后缀 基础操作 查看MySQL Server支持的…

C++教程(一)开发环境visual studio的安装——图文详细

一、visual studio下载地址&#xff1a; 1、百度网盘 链接&#xff1a;https://pan.baidu.com/s/1QJosSoAT7EumuvyjtC_1Iw?pwdwuqz 提取码&#xff1a;wuqz 2、官网下载 Visual Studio: 面向软件开发人员和 Teams 的 IDE 和代码编辑器 (microsoft.com)https://visualstudio.…

【Linux】vi编辑器的使用,要求能新建、编辑、保存一个文本文件。

&#xff08;1&#xff09;点击”应用程序”→ “附件”→“终端”&#xff0c;打开终端&#xff0c;在终端输入命令&#xff1a; [rootlocalhost root]#vi kk.c按 i 键&#xff0c;进入插入状态。 &#xff08;2&#xff09;输入以下C程序 #include<stdio.h>int main( …

【CEEMDAN-WOA-LSTM】完备集合经验模态分解-鲸鱼优化-长短时记忆神经网络研究(Python代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Java用native修饰的方法

今天看JDK ServerSocket源代码的时候&#xff0c;通过层层调用&#xff0c;到了用native修饰的方法&#xff0c;然后再也跟不下去了。 例如sun.nio.ch.Net类中下面的方法&#xff1a; Java方法如果用native修饰&#xff0c;就表示这个方法的实现不是用java实现的&#xff0c…

Element Ui Tree组件实现增、删、改、查、拖拽节点 的树形结构

介绍&#xff1a;首先组件 | Element官网某些功能都具备了&#xff0c;这里我就把这些功能结合在一起更完美的使用&#xff0c;其次编辑节点官网是没有实例&#xff0c;所以这里搞了一套较完整的功能&#xff0c;其次编辑和添加&#xff0c;这里直接使用了弹窗&#xff08;顾及…

单位列表单列出来,假(封装)组件

效果图&#xff1a; 因为每个页面都用到这个单位&#xff0c;所以把单位列表单列出来&#xff0c;假装是个封装的组件&#xff0c;在其他页面直接用。 源码&#xff1a; <template><div style"height: 48rem;overflow-y: scroll"><h4>单位列表<…

阿里云国际站代理商:阿里云是干什么的?阿里云app和建网站有什么关系?

标题&#xff1a;阿里云是干什么的&#xff1f;阿里云app和建网站有什么关系&#xff1f;   一、解析阿里云的业务范围   阿里云&#xff0c;作为阿里巴巴集团的关键业务板块&#xff0c;主要提供云计算、大数据、人工智能及其他信息化服务。通过其全球网络&#xff0c;阿里…