JavaFx 生成二维码工具类封装

打印 上一主题 下一主题

主题 877|帖子 877|积分 2646

原文地址: JavaFx 生成二维码工具类封装 - Stars-One的杂货小窝
之前星之音乐下载器有需要生成二维码功能,当时用的是一个开源库来实现的,但是没过多久,发现那个库依赖太多,有个http-client的依赖,把软件都搞大了一倍,而且有时候开发的时候下载依赖还报错,就想换个方案
于是在网上找了下解决方案,最终只需要依赖两个zxing的两个依赖即可实现功能
本文基于TornadoFx框架进行编写,封装工具代码是kotlin版本,工具类已经封装在common-controls库中
工具支持带logo图标,带底部文本的二维码生成
代码封装

1.引入依赖
  1. <dependency>
  2.     <groupId>com.google.zxing</groupId>
  3.     <artifactId>core</artifactId>
  4.     <version>3.5.0</version>
  5. </dependency>
  6. <dependency>
  7.     <groupId>com.google.zxing</groupId>
  8.     <artifactId>javase</artifactId>
  9.     <version>3.5.0</version>
  10. </dependency>
复制代码
2.使用

由于工具代码过多不便阅读,就先讲些使用,工具代码就放下面了
比较核心的就两个方法,如下面代码所示,其他的方法是带Swing关键字,就是生成Swing包中的Image对象
getQRcodeFxImg()方法就是直接生成Fx的Image对象,可以JavaFx中直接使用
  1. /**
  2. * 初始化设置
  3. *
  4. * @param qrcodeSize 二维码尺寸,默认为320(即320*320)
  5. * @param logoSize logo图标尺寸,默认为80(即80*80)
  6. * @param bottomTextSize 底部文字大小,默认20px
  7. * @param qrcodeType 二维码图片格式,默认为png
  8. */
  9. fun initConfig(qrcodeSize: Int = 320, logoSize: Int = 80, bottomTextSize: Int = 20, qrcodeType: String = "PNG")
  10. /**
  11. * 生成二维码图片
  12. *
  13. * @param data 二维码文本内容
  14. * @param logoPath 图标图片的路径
  15. * @param bottomText 底部文字
  16. * @return fx的img对象
  17. */
  18. fun getQRcodeFxImg(data: String?, logoPath: String?=null, bottomText: String?=null): WritableImage
复制代码
使用的话也比较简单:
  1. //得到的swing的image对象
  2. val buImg = QRCodeUtil.getQRcodeFxImg("这是测试文本")
  3. val buImg1 = QRCodeUtil.getQRcodeFxImg("这是测试文本", null, "底部文字")
  4. val buImg2 = QRCodeUtil.getQRcodeFxImg("这是测试文本", "/x5.jpg", "底部文字")
  5. val list = listOf(buImg, buImg1, buImg2)
  6. hbox(20.0) {
  7.     list.forEach {
  8.         imageview(it) {
  9.             fitWidth = 200.0
  10.             fitHeight = 200.0
  11.         }
  12.     }
  13. }
复制代码
3.工具库代码
  1. /**
  2. * 二维码生成工具类
  3. * Created by stars-one
  4. */
  5. object QRCodeUtil {
  6.     private var QRCODE_SIZE = 320 // 二维码尺寸,宽度和高度均是320
  7.     private var LOGO_SIZE = 80 // 二维码里logo的尺寸,宽高一致 80*80
  8.     private var BOTTOM_TEXT_SIZE = 20 // 底部文本的文字大小
  9.     private var FORMAT_TYPE = "PNG" // 二维码图片类型
  10.     /**
  11.      * 初始化设置
  12.      *
  13.      * @param qrcodeSize 二维码尺寸,默认为320(即320*320)
  14.      * @param logoSize logo图标尺寸,默认为80(即80*80)
  15.      * @param bottomTextSize 底部文字大小,默认20px
  16.      * @param qrcodeType 二维码图片格式,默认为png
  17.      */
  18.     fun initConfig(qrcodeSize: Int = 320, logoSize: Int = 80, bottomTextSize: Int = 20, qrcodeType: String = "PNG") {
  19.         QRCODE_SIZE = qrcodeSize
  20.         LOGO_SIZE = logoSize
  21.         BOTTOM_TEXT_SIZE = bottomTextSize
  22.         FORMAT_TYPE = qrcodeType
  23.     }
  24.     /**
  25.      * 生成二维码图片
  26.      *
  27.      * @param data 二维码文本内容
  28.      * @param logoPath 图标图片的路径
  29.      * @param bottomText 底部文字
  30.      * @return
  31.      */
  32.     fun getQRcodeFxImg(data: String?, logoPath: String?=null, bottomText: String?=null): WritableImage {
  33.         val resources = ResourceLookup(this)
  34.         val url = if (logoPath == null) {
  35.             null
  36.         } else {
  37.             resources.url(logoPath)
  38.         }
  39.         val swingImg = getQRCodeSwingImg(data, url, bottomText)
  40.         return SwingFXUtils.toFXImage(swingImg,null)
  41.     }
  42.     /**
  43.      * 默认需要logo,无底部文字
  44.      * 返回 BufferedImage 可以使用ImageIO.write(BufferedImage, "png", outputStream);输出
  45.      *
  46.      * @param dataStr
  47.      * @return 返回 BufferedImage 可以使用ImageIO.write(BufferedImage, "png", outputStream);输出
  48.      */
  49.     @Throws(Exception::class)
  50.     fun getQRCodeSwingImg(dataStr: String?): BufferedImage {
  51.         return getQRCodeSwingImg(dataStr, null, null)
  52.     }
  53.     /**
  54.      * 默认需要logo,无底部文字
  55.      *
  56.      * @param dataStr
  57.      * @return 返回字节数组
  58.      */
  59.     @Throws(Exception::class)
  60.     fun getQRCodeByte(dataStr: String?): ByteArray {
  61.         val bufferedImage = getQRCodeSwingImg(dataStr, null, null)
  62.         val outputStream = ByteArrayOutputStream()
  63.         ImageIO.write(bufferedImage, FORMAT_TYPE, outputStream)
  64.         return outputStream.toByteArray()
  65.     }
  66.     /**
  67.      * 默认需要logo,包含底部文字 文字为空则不显示文字
  68.      * 返回 BufferedImage 可以使用ImageIO.write(BufferedImage, "png", outputStream);输出
  69.      *
  70.      * @param dataStr
  71.      * @return
  72.      */
  73.     @Throws(Exception::class)
  74.     fun getQRCodeSwingImg(dataStr: String?, bottomText: String?): BufferedImage {
  75.         return getQRCodeSwingImg(dataStr, null, bottomText)
  76.     }
  77.     /**
  78.      * 默认需要logo,包含底部文字 文字为空则不显示文字
  79.      *
  80.      * @param dataStr
  81.      * @return 返回字节数组
  82.      */
  83.     @Throws(Exception::class)
  84.     fun getQRCodeByte(dataStr: String?, bottomText: String?): ByteArray {
  85.         val bufferedImage = getQRCodeSwingImg(dataStr, null, bottomText)
  86.         val outputStream = ByteArrayOutputStream()
  87.         ImageIO.write(bufferedImage, FORMAT_TYPE, outputStream)
  88.         return outputStream.toByteArray()
  89.     }
  90.     /**
  91.      * 获取二维码图片
  92.      *
  93.      * @param dataStr    二维码内容
  94.      * @param needLogo   是否需要添加logo
  95.      * @param bottomText 底部文字       为空则不显示
  96.      * @return
  97.      */
  98.     @Throws(Exception::class)
  99.     fun getQRCodeSwingImg(dataStr: String?, url: URL?, bottomText: String?): BufferedImage {
  100.         if (dataStr == null) {
  101.             throw RuntimeException("未包含任何信息")
  102.         }
  103.         val hints = HashMap<EncodeHintType, Any?>()
  104.         hints[EncodeHintType.CHARACTER_SET] = "utf-8" //定义内容字符集的编码
  105.         hints[EncodeHintType.ERROR_CORRECTION] = ErrorCorrectionLevel.L //定义纠错等级
  106.         hints[EncodeHintType.MARGIN] = 1
  107.         val qrCodeWriter = QRCodeWriter()
  108.         val bitMatrix = qrCodeWriter.encode(dataStr, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints)
  109.         val width = bitMatrix.width
  110.         val height = bitMatrix.height
  111.         var tempHeight = height
  112.         if (StringUtils.isNotBlank(bottomText)) {
  113.             tempHeight = tempHeight + 12
  114.         }
  115.         val image = BufferedImage(width, tempHeight, BufferedImage.TYPE_INT_RGB)
  116.         for (x in 0 until width) {
  117.             for (y in 0 until height) {
  118.                 image.setRGB(x, y, if (bitMatrix[x, y]) -0x1000000 else -0x1)
  119.             }
  120.         }
  121.         // 判断是否添加logo
  122.         if (url != null) {
  123.             insertLogoImage(image, url)
  124.         }
  125.         // 判断是否添加底部文字
  126.         if (StringUtils.isNotBlank(bottomText)) {
  127.             addFontImage(image, bottomText)
  128.         }
  129.         return image
  130.     }
  131.     /**
  132.      * 插入logo图片
  133.      *
  134.      * @param source 二维码图片
  135.      * @throws Exception
  136.      */
  137.     @Throws(Exception::class)
  138.     private fun insertLogoImage(source: BufferedImage, url: URL) {
  139.         var src: Image = ImageIO.read(url)
  140.         val width = LOGO_SIZE
  141.         val height = LOGO_SIZE
  142.         val image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH)
  143.         val tag = BufferedImage(width, height, BufferedImage.TYPE_INT_RGB)
  144.         val g = tag.graphics
  145.         g.drawImage(image, 0, 0, null) // 绘制缩小后的图
  146.         g.dispose()
  147.         src = image
  148.         // 插入LOGO
  149.         val graph = source.createGraphics()
  150.         val x = (QRCODE_SIZE - width) / 2
  151.         val y = (QRCODE_SIZE - height) / 2
  152.         graph.drawImage(src, x, y, width, height, null)
  153.         val shape: Shape = RoundRectangle2D.Float(x.toFloat(), y.toFloat(), width.toFloat(), width.toFloat(), 6f, 6f)
  154.         graph.stroke = BasicStroke(3f)
  155.         graph.draw(shape)
  156.         graph.dispose()
  157.     }
  158.     private fun addFontImage(source: BufferedImage, declareText: String?) {
  159.         //生成image
  160.         val defineWidth = QRCODE_SIZE
  161.         val defineHeight = 20
  162.         val textImage = BufferedImage(defineWidth, defineHeight, BufferedImage.TYPE_INT_RGB)
  163.         val g2 = textImage.graphics as Graphics2D
  164.         //开启文字抗锯齿
  165.         g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON)
  166.         g2.background = Color.WHITE
  167.         g2.clearRect(0, 0, defineWidth, defineHeight)
  168.         g2.paint = Color.BLACK
  169.         val context = g2.fontRenderContext
  170.         //部署linux需要注意 linux无此字体会显示方块
  171.         val font = Font("宋体", Font.BOLD, BOTTOM_TEXT_SIZE)
  172.         g2.font = font
  173.         val lineMetrics = font.getLineMetrics(declareText, context)
  174.         val fontMetrics: FontMetrics = FontDesignMetrics.getMetrics(font)
  175.         val offset = ((defineWidth - fontMetrics.stringWidth(declareText)) / 2).toFloat()
  176.         val y = (defineHeight + lineMetrics.ascent - lineMetrics.descent - lineMetrics.leading) / 2
  177.         g2.drawString(declareText, offset.toInt(), y.toInt())
  178.         val graph = source.createGraphics()
  179.         //开启文字抗锯齿
  180.         graph.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON)
  181.         //添加image
  182.         val width = textImage.getWidth(null)
  183.         val height = textImage.getHeight(null)
  184.         val src: Image = textImage
  185.         graph.drawImage(src, 0, QRCODE_SIZE - 8, width, height, Color.WHITE, null)
  186.         graph.dispose()
  187.     }
  188. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

大连全瓷种植牙齿制作中心

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表