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; } }
生成的效果如下: