zoukankan      html  css  js  c++  java
  • Java 基于Graphics2D绘制电子收据图片

    接到一个生成电子收据的需求,网上无模板,得自行设计

    参考了 这篇文章 https://blog.csdn.net/qq_26212181/article/details/97621758 

    生成二维码的代码,网上也有很多例子。

    难度其实不大,但调整样式比较费时,贴出来让大家参考绘制。

    package xxx.service.impl;
    import com.github.binarywang.utils.qrcode.MatrixToImageWriter;
    import com.google.zxing.BarcodeFormat;
    import com.google.zxing.EncodeHintType;
    import com.google.zxing.WriterException;
    import com.google.zxing.common.BitMatrix;
    import com.google.zxing.qrcode.QRCodeWriter;
    import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
    import lombok.SneakyThrows;
    import org.apache.shiro.SecurityUtils;
    import org.jeecg.common.system.vo.LoginUser;
    import org.jeecg.common.util.CommonUtils;
    import org.junit.Test;
    import org.springframework.stereotype.Service;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import javax.imageio.ImageIO;
    import java.awt.*;
    import java.awt.image.BufferedImage;
    import java.io.*;
    import java.util.Hashtable;/**
     * @Description: 电子票据表
     * @Author: jeecg-boot
     * @Date:   2021-01-25
     * @Version: V1.0
     */
    @Service
    public class DemoServiceImpl{
    
        @SneakyThrows
        @Test
        public void main() throws FileNotFoundException, IOException {
            String id = IdUtilWorker.IdUtil();//随机字符,这里是用雪花算法生成的字符串id
            int rowheight = 45;//行高
            int startHeight = 50;//余留上方像素
            int startWidth = 15;//余留左方像素
            int imageHeight = 360;
            int imageWidth =950;
            //得到图片缓冲区
            BufferedImage bi = new BufferedImage(imageWidth,imageHeight,BufferedImage.TYPE_INT_RGB);//INT精确度达到一定,RGB三原色,高度70,宽度150
    
            //得到它的绘制环境(这张图片的笔)
            //Graphics2D g2 = (Graphics2D) bi.getGraphics();
    
            Graphics2D g2 =bi.createGraphics();
            //设置颜色
            g2.setColor(Color.WHITE);
            g2.fillRect(0,0,imageWidth,imageHeight);//填充整张图片(其实就是设置背景颜色)
    
            //画横线
            for (int j = 0; j < 5; j++) {
                g2.setColor(Color.darkGray);
                g2.drawLine(startWidth, startHeight + (j + 1) * rowheight, imageWidth - 15,
                        startHeight + (j + 1) * rowheight);
            }
            // 画竖线
            int rightLine;
            g2.setColor(Color.gray);
            for (int k = 0; k < 2; k++) {
                rightLine = startWidth + k * (imageWidth - startWidth * 2 );
                g2.drawLine(rightLine, startHeight + rowheight, rightLine,
                        startHeight + 5 * rowheight);
            }
            g2.setColor(Color.BLACK);//设置背景颜色
            //插入二维码
            byte[] qrCode = getQRCodeImage(id,60,60);
            InputStream buffIn = new ByteArrayInputStream(qrCode, 0, qrCode.length);
            Image  bufferedImage =(Image) ImageIO.read(buffIn);
            g2.drawImage(bufferedImage,startWidth,10,null); //向图片左上插入二维码
            g2.setFont(new Font("黑体",Font.BOLD,20)); //设置字体:字体、字号、大小
            g2.drawString("XX有限责任公司收款收据      NO.", startWidth*19, rowheight);
    
            //以上画好了底图,开始插入票据信息
    
            g2.setFont(new Font("宋体", Font.CENTER_BASELINE, 14));
            //表头填充
            g2.drawString("0408601", imageWidth-startWidth*8, rowheight);
            g2.drawString("合同号:20210203xxxxxxxx", startWidth, startHeight+rowheight-3);
            g2.drawString("日期:  2021年2月3日",imageWidth - startWidth * 13, startHeight+rowheight-3);
            //调整字体
            g2.setFont(new Font("宋体", Font.CENTER_BASELINE, 17));
            //第一行填充
            g2.drawString("今日收到 张三 交来 解放路53号安居苑3栋1单元2048号 住宅保证金",startWidth*2, startHeight+rowheight*2-10);
            //第二行填充
            g2.drawString("¥:  790",imageWidth - startWidth * 13, startHeight+rowheight*3-10);
            //第三行填充
            g2.drawString("备注:  测试生成电子票据",startWidth*2, startHeight+rowheight*4-10);
            //第四行填充
            g2.drawString("缴费方式: 刷卡( )  转账( )  支付宝(●)  微信( )  现金( ) ",startWidth*2, startHeight+rowheight*5-10);
            //底部填充
            g2.drawString("开票单位(盖章有效)",startWidth*2, startHeight+rowheight*6-20);
            g2.drawString("开票人:韩梅梅",startWidth*25, startHeight+rowheight*6-20);
            g2.drawString("承租人(签名)",startWidth*50, startHeight+rowheight*6-20);
            //调整字体
            g2.setFont(new Font("宋体", Font.BOLD, 18));
            g2.drawString("人民币(大写):  漆佰玖拾圆整",startWidth*2, startHeight+rowheight*3-10);//第二行大写金额需要加粗,所以放在最后
            //因为2D画图画字体会有锯齿,而graphics2D类有抗锯齿和画笔柔顺的开关,设置如下
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);
            g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            Stroke s = new BasicStroke(imageWidth, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER);
            g2.setStroke(s);
    
            ImageIO.write(bi,"JPEG",new FileOutputStream("F:/codeCreateIMG/a"+id+".jpg"));//保存图片 JPEG表示保存格式
         //释放内存,解决文件占用问题
         bi.getGraphics().dispose();
         bi=null;
         System.gc();
        }
    
        //生成二维码
        // 编码格式
        private static final String CHARSET = "utf-8";
        private byte[] getQRCodeImage(String text, int width, int height) throws WriterException, IOException {
            Hashtable hints = new Hashtable();
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
            hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
            hints.put(EncodeHintType.MARGIN, 1);
            QRCodeWriter qrCodeWriter = new QRCodeWriter();
            BitMatrix bitMatrix = qrCodeWriter.encode(text, BarcodeFormat.QR_CODE, width, height, hints);
            ByteArrayOutputStream pngOutputStream = new ByteArrayOutputStream();
            MatrixToImageWriter.writeToStream(bitMatrix, "PNG", pngOutputStream);
            byte[] pngData = pngOutputStream.toByteArray();
            return pngData;
        }
    
    
    }

    生成的效果如下:

  • 相关阅读:
    labview 中的一些简写全称
    socket
    putty
    在波形图表中显示多条曲线
    简单的通电延时触发电路
    Linux sed 批量替换多个文件中的字符串
    PhpMyAdmin管理,登录多台远程MySQL服务器
    MySQL客户端工具推荐
    Redis的几个认识误区
    Redis 的 5 个常见使用场景
  • 原文地址:https://www.cnblogs.com/Lbox/p/14368349.html
Copyright © 2011-2022 走看看