JavaFx 生成二维码工具类封装

原文地址: JavaFx 生成二维码工具类封装 - Stars-One的杂货小窝

之前星之音乐下载器有需要生成二维码功能,当时用的是一个开源库来实现的,但是没过多久,发现那个库依赖太多,有个http-client的依赖,把软件都搞大了一倍,而且有时候开发的时候下载依赖还报错,就想换个方案

于是在网上找了下解决方案,最终只需要依赖两个zxing的两个依赖即可实现功能

本文基于TornadoFx框架进行编写,封装工具代码是kotlin版本,工具类已经封装在common-controls库中

工具支持带logo图标,带底部文本的二维码生成

代码封装

1.引入依赖

<dependency>     <groupId>com.google.zxing</groupId>     <artifactId>core</artifactId>     <version>3.5.0</version> </dependency> <dependency>     <groupId>com.google.zxing</groupId>     <artifactId>javase</artifactId>     <version>3.5.0</version> </dependency> 

2.使用

由于工具代码过多不便阅读,就先讲些使用,工具代码就放下面了

比较核心的就两个方法,如下面代码所示,其他的方法是带Swing关键字,就是生成Swing包中的Image对象

getQRcodeFxImg()方法就是直接生成Fx的Image对象,可以JavaFx中直接使用

/**  * 初始化设置  *  * @param qrcodeSize 二维码尺寸,默认为320(即320*320)  * @param logoSize logo图标尺寸,默认为80(即80*80)  * @param bottomTextSize 底部文字大小,默认20px  * @param qrcodeType 二维码图片格式,默认为png  */ fun initConfig(qrcodeSize: Int = 320, logoSize: Int = 80, bottomTextSize: Int = 20, qrcodeType: String = "PNG")  /**  * 生成二维码图片  *  * @param data 二维码文本内容  * @param logoPath 图标图片的路径  * @param bottomText 底部文字  * @return fx的img对象  */ fun getQRcodeFxImg(data: String?, logoPath: String?=null, bottomText: String?=null): WritableImage 

使用的话也比较简单:

//得到的swing的image对象 val buImg = QRCodeUtil.getQRcodeFxImg("这是测试文本") val buImg1 = QRCodeUtil.getQRcodeFxImg("这是测试文本", null, "底部文字") val buImg2 = QRCodeUtil.getQRcodeFxImg("这是测试文本", "/x5.jpg", "底部文字")  val list = listOf(buImg, buImg1, buImg2)  hbox(20.0) {     list.forEach {         imageview(it) {             fitWidth = 200.0             fitHeight = 200.0         }     } } 

3.工具库代码

/**  * 二维码生成工具类  * Created by stars-one  */ object QRCodeUtil {     private var QRCODE_SIZE = 320 // 二维码尺寸,宽度和高度均是320     private var LOGO_SIZE = 80 // 二维码里logo的尺寸,宽高一致 80*80     private var BOTTOM_TEXT_SIZE = 20 // 底部文本的文字大小     private var FORMAT_TYPE = "PNG" // 二维码图片类型      /**      * 初始化设置      *      * @param qrcodeSize 二维码尺寸,默认为320(即320*320)      * @param logoSize logo图标尺寸,默认为80(即80*80)      * @param bottomTextSize 底部文字大小,默认20px      * @param qrcodeType 二维码图片格式,默认为png      */     fun initConfig(qrcodeSize: Int = 320, logoSize: Int = 80, bottomTextSize: Int = 20, qrcodeType: String = "PNG") {         QRCODE_SIZE = qrcodeSize         LOGO_SIZE = logoSize         BOTTOM_TEXT_SIZE = bottomTextSize         FORMAT_TYPE = qrcodeType     }      /**      * 生成二维码图片      *      * @param data 二维码文本内容      * @param logoPath 图标图片的路径      * @param bottomText 底部文字      * @return      */     fun getQRcodeFxImg(data: String?, logoPath: String?=null, bottomText: String?=null): WritableImage {         val resources = ResourceLookup(this)         val url = if (logoPath == null) {             null         } else {             resources.url(logoPath)         }         val swingImg = getQRCodeSwingImg(data, url, bottomText)         return SwingFXUtils.toFXImage(swingImg,null)     }      /**      * 默认需要logo,无底部文字      * 返回 BufferedImage 可以使用ImageIO.write(BufferedImage, "png", outputStream);输出      *      * @param dataStr      * @return 返回 BufferedImage 可以使用ImageIO.write(BufferedImage, "png", outputStream);输出      */     @Throws(Exception::class)     fun getQRCodeSwingImg(dataStr: String?): BufferedImage {         return getQRCodeSwingImg(dataStr, null, null)     }      /**      * 默认需要logo,无底部文字      *      * @param dataStr      * @return 返回字节数组      */     @Throws(Exception::class)     fun getQRCodeByte(dataStr: String?): ByteArray {         val bufferedImage = getQRCodeSwingImg(dataStr, null, null)         val outputStream = ByteArrayOutputStream()         ImageIO.write(bufferedImage, FORMAT_TYPE, outputStream)         return outputStream.toByteArray()     }      /**      * 默认需要logo,包含底部文字 文字为空则不显示文字      * 返回 BufferedImage 可以使用ImageIO.write(BufferedImage, "png", outputStream);输出      *      * @param dataStr      * @return      */     @Throws(Exception::class)     fun getQRCodeSwingImg(dataStr: String?, bottomText: String?): BufferedImage {         return getQRCodeSwingImg(dataStr, null, bottomText)     }      /**      * 默认需要logo,包含底部文字 文字为空则不显示文字      *      * @param dataStr      * @return 返回字节数组      */     @Throws(Exception::class)     fun getQRCodeByte(dataStr: String?, bottomText: String?): ByteArray {         val bufferedImage = getQRCodeSwingImg(dataStr, null, bottomText)         val outputStream = ByteArrayOutputStream()         ImageIO.write(bufferedImage, FORMAT_TYPE, outputStream)         return outputStream.toByteArray()     }      /**      * 获取二维码图片      *      * @param dataStr    二维码内容      * @param needLogo   是否需要添加logo      * @param bottomText 底部文字       为空则不显示      * @return      */     @Throws(Exception::class)     fun getQRCodeSwingImg(dataStr: String?, url: URL?, bottomText: String?): BufferedImage {         if (dataStr == null) {             throw RuntimeException("未包含任何信息")         }         val hints = HashMap<EncodeHintType, Any?>()         hints[EncodeHintType.CHARACTER_SET] = "utf-8" //定义内容字符集的编码         hints[EncodeHintType.ERROR_CORRECTION] = ErrorCorrectionLevel.L //定义纠错等级         hints[EncodeHintType.MARGIN] = 1         val qrCodeWriter = QRCodeWriter()         val bitMatrix = qrCodeWriter.encode(dataStr, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints)         val width = bitMatrix.width         val height = bitMatrix.height         var tempHeight = height         if (StringUtils.isNotBlank(bottomText)) {             tempHeight = tempHeight + 12         }         val image = BufferedImage(width, tempHeight, BufferedImage.TYPE_INT_RGB)         for (x in 0 until width) {             for (y in 0 until height) {                 image.setRGB(x, y, if (bitMatrix[x, y]) -0x1000000 else -0x1)             }         }         // 判断是否添加logo         if (url != null) {             insertLogoImage(image, url)         }         // 判断是否添加底部文字         if (StringUtils.isNotBlank(bottomText)) {             addFontImage(image, bottomText)         }         return image     }      /**      * 插入logo图片      *      * @param source 二维码图片      * @throws Exception      */     @Throws(Exception::class)     private fun insertLogoImage(source: BufferedImage, url: URL) {         var src: Image = ImageIO.read(url)         val width = LOGO_SIZE         val height = LOGO_SIZE         val image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH)         val tag = BufferedImage(width, height, BufferedImage.TYPE_INT_RGB)         val g = tag.graphics         g.drawImage(image, 0, 0, null) // 绘制缩小后的图         g.dispose()         src = image          // 插入LOGO         val graph = source.createGraphics()         val x = (QRCODE_SIZE - width) / 2         val y = (QRCODE_SIZE - height) / 2         graph.drawImage(src, x, y, width, height, null)         val shape: Shape = RoundRectangle2D.Float(x.toFloat(), y.toFloat(), width.toFloat(), width.toFloat(), 6f, 6f)         graph.stroke = BasicStroke(3f)         graph.draw(shape)         graph.dispose()     }      private fun addFontImage(source: BufferedImage, declareText: String?) {         //生成image         val defineWidth = QRCODE_SIZE         val defineHeight = 20         val textImage = BufferedImage(defineWidth, defineHeight, BufferedImage.TYPE_INT_RGB)         val g2 = textImage.graphics as Graphics2D         //开启文字抗锯齿         g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON)         g2.background = Color.WHITE         g2.clearRect(0, 0, defineWidth, defineHeight)         g2.paint = Color.BLACK         val context = g2.fontRenderContext         //部署linux需要注意 linux无此字体会显示方块         val font = Font("宋体", Font.BOLD, BOTTOM_TEXT_SIZE)         g2.font = font         val lineMetrics = font.getLineMetrics(declareText, context)         val fontMetrics: FontMetrics = FontDesignMetrics.getMetrics(font)         val offset = ((defineWidth - fontMetrics.stringWidth(declareText)) / 2).toFloat()         val y = (defineHeight + lineMetrics.ascent - lineMetrics.descent - lineMetrics.leading) / 2         g2.drawString(declareText, offset.toInt(), y.toInt())         val graph = source.createGraphics()         //开启文字抗锯齿         graph.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON)         //添加image         val width = textImage.getWidth(null)         val height = textImage.getHeight(null)         val src: Image = textImage         graph.drawImage(src, 0, QRCODE_SIZE - 8, width, height, Color.WHITE, null)         graph.dispose()     } } 

发表评论

评论已关闭。

相关文章