本篇,笔者介绍下自己用java开发的一款QR码生成器图形化工具。

qrcode编码、解码功能依赖于google的二维码开源库google.zxing。

笔者项目github地址: https://github.com/jellyflu/qrTool

废话少讲,先上张最终运行效果图。

整体项目结构如下(开发IDE是STS)。

具体java实现代码如下 :

QRJFrame.java   (主窗体)

package com.tingcream.qrTool.view;import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.SwingConstants;
import javax.swing.border.EmptyBorder;
import javax.swing.filechooser.FileNameExtensionFilter;import org.apache.commons.io.FileUtils;import com.tingcream.qrTool.qrcode.QRCodeUtil;import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;public class QRJFrame extends JFrame {/****/private static final long serialVersionUID = 1L;private JPanel contentPane;private JPanel   panel1 ;//tab中面板1  面板2private JLabel label1 ;//qr码 图形显示框private JLabel label2;private JLabel lblQr;private JButton btn1;//panel1 生成private JButton btn3;//panel1 清空private JTextArea textArea1;//原文 文本域private String recentDir;//最近访问的目录private JButton btn4;// 打开img文件private JButton btn5;//panel1 保存/*** Launch the application.*/public static void main(String[] args) {EventQueue.invokeLater(new Runnable() {public void run() {try {QRJFrame frame = new QRJFrame();frame.setVisible(true);frame.setLocationRelativeTo(null);//主窗体居中} catch (Exception e) {e.printStackTrace();}}});}/*** Create the frame.* @throws IOException*/public QRJFrame() throws IOException {setResizable(false);setFont(new Font("微软雅黑", Font.PLAIN, 18));setTitle("QR生成器");setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setBounds(100, 100, 464, 636);contentPane = new JPanel();contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));contentPane.setLayout(new BorderLayout(0, 0));setContentPane(contentPane);JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);tabbedPane.setFont(new Font("微软雅黑", Font.PLAIN, 18));contentPane.add(tabbedPane, BorderLayout.CENTER);panel1 = new JPanel();tabbedPane.addTab("QR生成", null, panel1, null);label1 = new JLabel("");label1.setVerticalAlignment(SwingConstants.TOP);label1.setBackground(Color.WHITE);setDefaultQrImg();label1.setHorizontalAlignment(SwingConstants.LEFT);label1.setFont(new Font("微软雅黑", Font.PLAIN, 18));label2 = new JLabel("原文内容:");label2.setFont(new Font("微软雅黑", Font.PLAIN, 18));JScrollPane scrollPane = new JScrollPane();lblQr = new JLabel("QR码  :");lblQr.setFont(new Font("微软雅黑", Font.PLAIN, 18));btn1 = new JButton("生成↓");btn1.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {generateQRImg(e);}});btn1.setFont(new Font("微软雅黑", Font.PLAIN, 18));btn3 = new JButton("清空");btn3.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {textArea1.setText("");setDefaultQrImg();}});btn3.setFont(new Font("微软雅黑", Font.PLAIN, 18));btn5 = new JButton("保存");btn5.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {saveQrImg(e);}});btn5.setFont(new Font("微软雅黑", Font.PLAIN, 18));btn4 = new JButton("选择");btn4.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {openQrImg(e);}});btn4.setFont(new Font("微软雅黑", Font.PLAIN, 18));GroupLayout  gl_panel1 = new GroupLayout(panel1);gl_panel1.setHorizontalGroup(gl_panel1.createParallelGroup(Alignment.LEADING).addGroup(gl_panel1.createSequentialGroup().addGroup(gl_panel1.createParallelGroup(Alignment.LEADING).addGroup(gl_panel1.createSequentialGroup().addGap(19).addGroup(gl_panel1.createParallelGroup(Alignment.TRAILING).addComponent(label2).addComponent(lblQr, GroupLayout.PREFERRED_SIZE, 76, GroupLayout.PREFERRED_SIZE))).addGroup(gl_panel1.createSequentialGroup().addContainerGap().addComponent(btn4, GroupLayout.PREFERRED_SIZE, 77, GroupLayout.PREFERRED_SIZE)).addGroup(gl_panel1.createSequentialGroup().addContainerGap().addComponent(btn5, GroupLayout.PREFERRED_SIZE, 77, GroupLayout.PREFERRED_SIZE))).addPreferredGap(ComponentPlacement.RELATED).addGroup(gl_panel1.createParallelGroup(Alignment.LEADING, false).addGroup(gl_panel1.createSequentialGroup().addComponent(btn1).addPreferredGap(ComponentPlacement.RELATED).addComponent(btn3, GroupLayout.PREFERRED_SIZE, 77, GroupLayout.PREFERRED_SIZE)).addComponent(label1, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addComponent(scrollPane)).addContainerGap(39, Short.MAX_VALUE)));gl_panel1.setVerticalGroup(gl_panel1.createParallelGroup(Alignment.LEADING).addGroup(gl_panel1.createSequentialGroup().addContainerGap().addGroup(gl_panel1.createParallelGroup(Alignment.LEADING).addComponent(label2).addComponent(scrollPane, GroupLayout.PREFERRED_SIZE, 152, GroupLayout.PREFERRED_SIZE)).addPreferredGap(ComponentPlacement.RELATED).addGroup(gl_panel1.createParallelGroup(Alignment.BASELINE).addComponent(btn1).addComponent(btn3, GroupLayout.PREFERRED_SIZE, 33, GroupLayout.PREFERRED_SIZE)).addGap(18).addGroup(gl_panel1.createParallelGroup(Alignment.LEADING).addGroup(gl_panel1.createSequentialGroup().addComponent(lblQr, GroupLayout.PREFERRED_SIZE, 24, GroupLayout.PREFERRED_SIZE).addPreferredGap(ComponentPlacement.RELATED).addComponent(btn5, GroupLayout.PREFERRED_SIZE, 33, GroupLayout.PREFERRED_SIZE).addGap(15).addComponent(btn4, GroupLayout.PREFERRED_SIZE, 33, GroupLayout.PREFERRED_SIZE)).addComponent(label1)).addContainerGap(21, Short.MAX_VALUE)));textArea1 = new JTextArea();textArea1.setFont(new Font("微软雅黑", Font.PLAIN, 18));scrollPane.setViewportView(textArea1);panel1.setLayout(gl_panel1);}//显示默认qr图形  空白图片private  void setDefaultQrImg() {label1.setIcon(new ImageIcon(QRJFrame.class.getResource("/com/tingcream/qrTool/img/blank_300_300.png")));}/*** 保存qr图形 到指定文件中* @author jelly* @param e*/void saveQrImg(ActionEvent e) {String text = textArea1.getText();if(text==null||text.trim().equals("")) {JOptionPane.showMessageDialog(null, "原文内容不能为空!");return ;}FileOutputStream  output=null;try {JFileChooser wjsave=null;if(recentDir!=null&&recentDir.trim().length()>0){wjsave=new JFileChooser(recentDir);}else{wjsave=new JFileChooser();}wjsave.setDialogType(JFileChooser.SAVE_DIALOG);wjsave.setVisible(true);wjsave.setDialogTitle("保存QR码到文件");int value= wjsave.showSaveDialog(null);if(value==JFileChooser.APPROVE_OPTION){//用户点击了保存File savefile= wjsave.getSelectedFile();// 保存的文件recentDir= savefile.getParent();//将文件目录保存到成员变量output=new FileOutputStream(savefile);QRCodeUtil.encode(text, null, output, true);}} catch (Exception e2) {e2.printStackTrace();}finally {if(output!=null) {try {output.close();} catch (IOException e1) {e1.printStackTrace();}}}}/*** 从本地选择(打开)qr图片文件* @author jelly* @param e*/void openQrImg(ActionEvent e) {try {JFileChooser wjopen=null;if(recentDir!=null&&recentDir.trim().length()>0){wjopen=new JFileChooser(recentDir);}else{wjopen=new JFileChooser();}wjopen.setDialogTitle("打开QR码文件");wjopen.setDialogType(JFileChooser.OPEN_DIALOG);wjopen.setVisible(true);wjopen.addChoosableFileFilter(new FileNameExtensionFilter("PNG文件(png)","png"));int value=wjopen.showOpenDialog(null);if(value==JFileChooser.APPROVE_OPTION){//用户点击了打开File openfile=  wjopen.getSelectedFile();byte[] bytes =FileUtils.readFileToByteArray(openfile);label1.setIcon(new ImageIcon(bytes));String text =QRCodeUtil.decode(new FileInputStream(openfile));textArea1.setText(text);}} catch (Exception e2) {e2.printStackTrace();}}/*** 生成qr图形 并在label1中显示* @author jelly* @param e*/void generateQRImg(ActionEvent e) {String text = textArea1.getText();if(text==null||text.trim().equals("")) {JOptionPane.showMessageDialog(null, "原文内容不能为空!");return ;}ByteArrayOutputStream output=new ByteArrayOutputStream();try {QRCodeUtil.encode(text, null, output, true);} catch (Exception e1) {e1.printStackTrace();JOptionPane.showMessageDialog(null, e1.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);}byte[] bytes =output.toByteArray();label1.setIcon(new ImageIcon(bytes));}}

QRCodeUtil.java

package com.tingcream.qrTool.qrcode;import java.awt.BasicStroke;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Shape;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Hashtable;
import javax.imageio.ImageIO;import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.Result;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;/*** 二维码工具类  google.zxing包** @author jelly*/
public class QRCodeUtil {private static final String CHARSET = "utf-8";private static final String FORMAT_NAME = "png";// 二维码尺寸private static final int QRCODE_SIZE = 300; //即 300 * 300 像素// LOGO宽度private static final int LOGO_WIDTH = 60;// LOGO高度private static final int LOGO_HEIGHT = 60;/*** 创建qrcode 二维码* @param content  原文内容* @param logoInput  可为null,若为null,则二维码中不会插入logo* @param needCompress  是否需要颜色* @return* @throws Exception*/@SuppressWarnings({ "unchecked", "rawtypes" })public  static BufferedImage createQrImage(String content,InputStream logoInput,boolean needCompress) throws Exception {Hashtable hints = new Hashtable();hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);hints.put(EncodeHintType.CHARACTER_SET, CHARSET);hints.put(EncodeHintType.MARGIN, 1);BitMatrix bitMatrix = new MultiFormatWriter().encode(content,BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);int width = bitMatrix.getWidth();int height = bitMatrix.getHeight();BufferedImage image = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);for (int x = 0; x < width; x++) {for (int y = 0; y < height; y++) {image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000: 0xFFFFFFFF);}}if (logoInput==null) {return image;}else {// 插入logo图片QRCodeUtil.insertLogo(image, logoInput, needCompress);return image;}}/*** 图形二维码中插入logo图形* @param source* @param logoPath* @param needCompress* @throws Exception*/private static void insertLogo(BufferedImage source, InputStream logoInput,boolean needCompress) throws Exception {Image src =ImageIO.read(logoInput);int width = src.getWidth(null);int height = src.getHeight(null);if (needCompress) { // 压缩LOGOif (width > LOGO_WIDTH) {width = LOGO_WIDTH;}if (height > LOGO_HEIGHT) {height = LOGO_HEIGHT;}Image image = src.getScaledInstance(width, height,Image.SCALE_SMOOTH);BufferedImage tag = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);Graphics g = tag.getGraphics();g.drawImage(image, 0, 0, null); // 绘制缩小后的图g.dispose();src = image;}// 插入LOGOGraphics2D graph = source.createGraphics();int x = (QRCODE_SIZE - width) / 2;int y = (QRCODE_SIZE - height) / 2;graph.drawImage(src, x, y, width, height, null);Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);graph.setStroke(new BasicStroke(3f));graph.draw(shape);graph.dispose();}/*** 二维码编码    xx* @param text   原文内容* @param logoIn  logo图 ,可为null* @param output  二维码图形输出outputstream* @param needCompress  是否需要颜色* @throws Exception*/public static void encode(String  text,InputStream logoIn,OutputStream output,boolean needCompress) throws Exception {BufferedImage image = createQrImage(text, logoIn, needCompress);ImageIO.write(image, FORMAT_NAME, output);}/*** 二维码解码 xx* @param in  二维码图input流* @return 原文内容* @throws Exception*/@SuppressWarnings({ "unchecked", "rawtypes" })public static String decode(InputStream in) throws Exception {BufferedImage  image=ImageIO.read(in);BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));Hashtable hints = new Hashtable();hints.put(DecodeHintType.CHARACTER_SET, CHARSET);Result  result = new MultiFormatReader().decode(bitmap, hints);return  result.getText();}//    public static void main(String[] args) throws Exception {
//
//      //二维码编码String text = "hello\n你好哈哈";OutputStream output=new FileOutputStream(new File("d:/qr.png"));QRCodeUtil.encode(text, null, output, true);
//
//      //二维码解码InputStream in=new FileInputStream(new File("d:/qr.png"));String result=QRCodeUtil.decode(in);System.out.println(result);
//    }}

BufferedImageLuminanceSource.java (google的LuminanceSource 封装)

package com.tingcream.qrTool.qrcode;import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import com.google.zxing.LuminanceSource;public class BufferedImageLuminanceSource extends LuminanceSource {private final BufferedImage image;private final int left;private final int top;public BufferedImageLuminanceSource(BufferedImage image) {this(image, 0, 0, image.getWidth(), image.getHeight());}public BufferedImageLuminanceSource(BufferedImage image, int left,int top, int width, int height) {super(width, height);int sourceWidth = image.getWidth();int sourceHeight = image.getHeight();if (left + width > sourceWidth || top + height > sourceHeight) {throw new IllegalArgumentException("Crop rectangle does not fit within image data.");}for (int y = top; y < top + height; y++) {for (int x = left; x < left + width; x++) {if ((image.getRGB(x, y) & 0xFF000000) == 0) {image.setRGB(x, y, 0xFFFFFFFF); // = white}}}this.image = new BufferedImage(sourceWidth, sourceHeight,BufferedImage.TYPE_BYTE_GRAY);this.image.getGraphics().drawImage(image, 0, 0, null);this.left = left;this.top = top;}public byte[] getRow(int y, byte[] row) {if (y < 0 || y >= getHeight()) {throw new IllegalArgumentException("Requested row is outside the image: " + y);}int width = getWidth();if (row == null || row.length < width) {row = new byte[width];}image.getRaster().getDataElements(left, top + y, width, 1, row);return row;}public byte[] getMatrix() {int width = getWidth();int height = getHeight();int area = width * height;byte[] matrix = new byte[area];image.getRaster().getDataElements(left, top, width, height, matrix);return matrix;}public boolean isCropSupported() {return true;}public LuminanceSource crop(int left, int top, int width, int height) {return new BufferedImageLuminanceSource(image, this.left + left,this.top + top, width, height);}public boolean isRotateSupported() {return true;}public LuminanceSource rotateCounterClockwise() {int sourceWidth = image.getWidth();int sourceHeight = image.getHeight();AffineTransform transform = new AffineTransform(0.0, -1.0, 1.0,0.0, 0.0, sourceWidth);BufferedImage rotatedImage = new BufferedImage(sourceHeight,sourceWidth, BufferedImage.TYPE_BYTE_GRAY);Graphics2D g = rotatedImage.createGraphics();g.drawImage(image, transform, null);g.dispose();int width = getWidth();return new BufferedImageLuminanceSource(rotatedImage, top,  sourceWidth - (left + width), getHeight(), width);}
}

项目pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.tingcream</groupId><artifactId>qrTool</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>qrTool</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><!-- https://mvnrepository.com/artifact/com.google.zxing/javase --><dependency><groupId>com.google.zxing</groupId><artifactId>javase</artifactId><version>3.2.1</version></dependency><!-- https://mvnrepository.com/artifact/com.google.zxing/core --><!--     <dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.2.1</version></dependency> --><!-- https://mvnrepository.com/artifact/commons-io/commons-io --><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version></dependency></dependencies>
</project>

qrcode二维码生成工具相关推荐

  1. Python的妙用,PyQt5+qrcode,Python制作二维码生成工具

    前言: 今天我们就利用PyQt5+qrcode制作一个简单的二维码生成工具吧.让我们愉快地开始吧~ 开发工具 Python版本:3.6.4 相关模块: PyQt5模块: qrcode模块: 以及一些P ...

  2. 支付宝支付 第五集:二维码生成工具

    支付宝支付 第五集:二维码生成工具 一.代码 目录结构 BufferedImageLuminanceSource.java package com.dzy.alipay.qrcode;import c ...

  3. 二维码 生成工具类(文件转Base64字符串,Base64字符串转文件)

    希望我的知识榨干了能帮到你解除困难,要是没有帮助你的,问度娘和知爹 一.POM.xml依赖下载 二.工具类提供 一.POM.xml依赖下载 <!-- 生成二维码依赖 --><depe ...

  4. Java:二维码生成工具类

    java 二维码生成工具类 需要引入的maven <!--Java 生成二维码 --> <dependency><groupId>com.google.zxing& ...

  5. 微信小程序二维码生成工具,后端二维码生成工具类。

    微信小程序开发二维码生成工具类 前言 业务背景 设计思路 具体实现 接下来我们进行工具的改造 前言 或许这是你搜寻的第n篇文章来解决你项目中的问题,虽然我不能去替你完全适配你的业务需求,但是我可以给你 ...

  6. QRCode二维码生成方案及其在带LOGO型二维码中的应用(2)

    QRCode二维码生成方案及其在带LOGO型二维码中的应用(2) 原文:QRCode二维码生成方案及其在带LOGO型二维码中的应用(2) 续前:QRCode二维码生成方案及其在带LOGO型二维码中的应 ...

  7. 二维码生成工具微信小程序源码下载

    二维码生成工具 支持上传二维码logo和调整尺寸背景颜色等等 无需域名与服务器 使用教程,用HBuilder X软件打卡项目然后运行到微信小程序即可 下方是演示图: 小程序源码下载地址: (已更新)二 ...

  8. 软件推荐——二维码生成工具(绿色版)

    Simple Code Generator 二维码生成工具 软件介绍: Simple Code Generator是一款适用于Windows的简单工具,它允许您快速生成二维码,以便在智能手机上使用应用 ...

  9. QT-C++二维码生成工具(支持中文等任何字符的使用)

    QT-C++二维码生成工具 前言 1.效果预览 1.核心程序 全部程序 前言 QT/C++生成二维码程序,支持二维码图片本地保存功能. 1.效果预览 1.核心程序 如下: // 生成二维码图片QStr ...

最新文章

  1. java 16进制与图片互转
  2. 泰安服务器维护公司,神云 泰安服务器
  3. 力扣(LeetCode)刷题,简单题(第6期)
  4. 小冰完成数亿元Pre-A轮融资,投资方为北极光创投和网易,还宣布了和老东家微软的战略合作...
  5. 打开sql server 验证
  6. [Modules]PrestaShop插件 模块 – 产品推荐模块 随机展示推荐产品
  7. 上行短信 写入mysql_7、上行短信处理服务 -功能详细设计 --短信平台
  8. c语言中闰年的流程图_C语言-算法与流程图
  9. java 8 list,JAVA8 ListListInteger list中再装一个list转成一个list操作
  10. 年底了,各大电商大促会员活动反馈万能模板,必备的PSD分层格式
  11. LeetCode : Intersection of Two Linked Lists
  12. matlab中注释多行
  13. win7工作组计算机无法连接打印机,win7无法访问共享打印机怎么解决
  14. MAC:更新失败无法进系统的解决方案
  15. 保姆级二进制安装高可用k8s集群文档(1.23.8)
  16. input搜索框 php,html搜索框怎么设置?html搜索框input标签的使用方法实例
  17. centos虚拟机重启网卡命令
  18. 浪潮IPBS9505S短接线刷固件(附教程)
  19. [PHP]用PHP自己写一个zoomeye的api(偷懒必备quq)
  20. 《黑客之道》--网络安全 黑客攻防教程 渗透测试 利用第三方服务对目标进行被动信息收集防止被发现

热门文章

  1. 学习日志-勉励自己-自律
  2. 专利解析|多维建模结合AI识别商品特征的方法
  3. 多学5个实用Excel技巧,工作早做完,比同事早下班
  4. 测评Mimick模型对词向量重构效果
  5. SpringBoot整合Shiro学习(上)
  6. 函数的使用:两个数取最小值
  7. 【元胞自动机】元胞自动机模拟交通事故道路通行量【含Matlab源码 356期】
  8. JS入门笔记九:循环精灵图案例
  9. sh_10_嵌套打印小星星
  10. 混沌的有关概念——1