JavaFx 生成二维码工具类封装

之前星之音乐下载器有需要生成二维码功能,当时用的是一个开源库来实现的,但是没过多久,发现那个库依赖太多,有个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.0fitHeight = 200.0}}
}

3.工具库代码  

/*** 二维码生成工具类* Created by stars-one*/
object QRCodeUtil {private var QRCODE_SIZE = 320 // 二维码尺寸,宽度和高度均是320private var LOGO_SIZE = 80 // 二维码里logo的尺寸,宽高一致 80*80private 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 = qrcodeSizeLOGO_SIZE = logoSizeBOTTOM_TEXT_SIZE = bottomTextSizeFORMAT_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] = 1val qrCodeWriter = QRCodeWriter()val bitMatrix = qrCodeWriter.encode(dataStr, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints)val width = bitMatrix.widthval height = bitMatrix.heightvar tempHeight = heightif (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)}}// 判断是否添加logoif (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_SIZEval height = LOGO_SIZEval image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH)val tag = BufferedImage(width, height, BufferedImage.TYPE_INT_RGB)val g = tag.graphicsg.drawImage(image, 0, 0, null) // 绘制缩小后的图g.dispose()src = image// 插入LOGOval graph = source.createGraphics()val x = (QRCODE_SIZE - width) / 2val y = (QRCODE_SIZE - height) / 2graph.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?) {//生成imageval defineWidth = QRCODE_SIZEval defineHeight = 20val 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.WHITEg2.clearRect(0, 0, defineWidth, defineHeight)g2.paint = Color.BLACKval context = g2.fontRenderContext//部署linux需要注意 linux无此字体会显示方块val font = Font("宋体", Font.BOLD, BOTTOM_TEXT_SIZE)g2.font = fontval 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) / 2g2.drawString(declareText, offset.toInt(), y.toInt())val graph = source.createGraphics()//开启文字抗锯齿graph.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON)//添加imageval width = textImage.getWidth(null)val height = textImage.getHeight(null)val src: Image = textImagegraph.drawImage(src, 0, QRCODE_SIZE - 8, width, height, Color.WHITE, null)graph.dispose()}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/51781.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JVM——垃圾回收器G1+垃圾回收调优

4.4 G1&#xff08;一个垃圾回收器&#xff09; 定义: 取代了CMS垃圾回收器。和CMS一样时并发的。 适用场景: 物理上分区&#xff0c;逻辑上分代。 相关JVM参数: -XX:UseG1GC-XX:G1HeapRegionSizesize-XX:MaxGCPauseMillistime 1) G1 垃圾回收阶段 三个回收阶段&#xff0…

kubeadm init 失败: failed to pull image k8s.gcr.io/etcd:3.4.13-0

一. kubeadm init 失败 报错: error execution phase preflight: [preflight] Some fatal errors occurred:[ERROR ImagePull]: failed to pull image k8s.gcr.io/kube-apiserver:v1.19.3: output: Error response from daemon: Get https://k8s.gcr.io/v2/: net/http: reque…

基于JSP+Servlet+mysql员工权限管理系统

基于JSPServletmysql员工权限管理系统 一、系统介绍二、功能展示四、其他系统实现五、获取源码 一、系统介绍 项目类型&#xff1a;Java web项目 项目名称&#xff1a;基于JSPServlet的员工权限管理系统[qxxt] 项目架构&#xff1a;B/S架构 开发语言&#xff1a;Java语言 …

Solidity 合约安全,常见漏洞(第三篇)

Solidity 合约安全&#xff0c;常见漏洞&#xff08;第三篇&#xff09; ERC20 代币问题 如果你只处理受信任的 ERC20 代币&#xff0c;这些问题大多不适用。然而&#xff0c;当与任意的或部分不受信任的 ERC20 代币交互时&#xff0c;就有一些需要注意的地方。 ERC20&#…

Docker 安装rabbitmq:3.12-management

拉取镜像&#xff1a; docker pull rabbitmq:3.12-management mkdir -p /usr/local/rabbitmq chmod 777 /usr/local/rabbitmq docker run -id --restartalways --namerabbitmq -v /usr/local/rabbitmq:/var/lib/rabbitmq -p 15672:15672 -p 5672:5672 -e RABBITMQ_DEFAULT_U…

如何在 Opera 中启用DNS over HTTPS

DNS over HTTPS&#xff08;基于HTTPS的DNS&#xff09;是一种更安全的浏览方式&#xff0c;但大多数 Web 浏览器默认情况下不启用它。了解如何在 Opera 浏览器中启用该功能。 您可能不知道这一点&#xff0c;但您的网络浏览器并不像您希望的那样私密或安全。您会看到&#xff…

助力品牌形象建设,FairGuard支持企业深度定制化

2022年&#xff0c;中国游戏市场实际销售收入与游戏用户规模出现近年来的首次下降&#xff0c;标志着游戏产业发展正式迈入存量时代。 存量市场时代&#xff0c;意味着游戏产品获取用户的难度逐渐加大&#xff0c;对于游戏的内容品质、技术实力和价值拓展等有了更高的要求。如…

C - 滑动窗口 /【模板】单调队列

Description 有一个长为 n 的序列 a&#xff0c;以及一个大小为 k 的窗口。现在这个从左边开始向右滑动&#xff0c;每次滑动一个单位&#xff0c;求出每次滑动后窗口中的最大值和最小值。 例如&#xff1a; The array is [1,3,−1,−3,5,3,6,7] and k3。 Input 输入一共有…

初出茅庐的小李博客之STM32CubeMx配置USART1增加打印功能

1.创建基于STM32F03C8T6工程 1.1配置时钟 选择外部高速时钟源HSE 1.2配置系统时钟树使其达到最大时钟72MHz&#xff08;最大系统时钟&#xff09; 配置串口1 生成代码 具体工程配置可参考上几篇博客&#xff0c;地址 初出茅庐的小李博客之STM32CubeMx驱动WS2812B实现幻彩&a…

深入理解Linux权限管理:保护系统安全的重要措施

Linux操作系统以其稳定性、可靠性和灵活性而受到广泛使用。其中一个关键特性是其强大的权限管理系统&#xff0c;它可以保护系统资源和用户数据的安全性。本文将深入探讨Linux权限管理的概念、原则和实践&#xff0c;帮助您理解如何正确配置和管理权限&#xff0c;以确保系统的…

​亚商投资顾问 早餐FM/0825 8月24日起全面暂停进口日本水产品

01/亚商投资顾问 早间导读 中国证监会召开机构投资者座谈会&#xff0c;引导更多中长期资金入市海关总署&#xff1a;8月24日起全面暂停进口日本水产品财政部&#xff1a;加强财税支持政策落实&#xff0c;促进中小企业高质量发展 02/亚商投资顾问 新闻早餐 // 热点聚焦 //…

PyTorch DataLoader 报错 “DataLoader worker exited unexpectedly“ 的解决方案

注意&#xff1a;博主没有重写d2l的源代码文件&#xff0c;而是创建了一个新的python文件&#xff0c;并重写了该方法。 一、代码运行日志 C:\Users\Administrator\anaconda3\envs\limu\python.exe G:/PyCharmProjects/limu-d2l/ch03/softmax_regression.py Traceback (most r…

通过python在unity里调用C#接口

log: 背景 最近在做虚拟人底层驱动sdk测试&#xff0c;因为后端使用的是C#,我个人更倾向于python编程辅助测试工作&#xff0c;测试sdk需要通过开发提供的接口方法文档&#xff0c;通过传测试场景参数调用方法进行单元测试 技术&工具 项目语言 C# 项目工具 unity 测试…

docker build -t 和 docker build -f 区别

docker build 是用于构建Docker镜像的命令&#xff0c;它允许你基于一个Dockerfile来创建一个镜像。在 docker build 命令中&#xff0c;有两个常用的选项 -t 和 -f&#xff0c;它们有不同的作用。 -t’选项&#xff1a; -t’选项用于指定构建出来的镜像的名称和标签。格式为 &…

如何才能设计出“好的”测试用例?

软件测试用例的设计质量直接影响到测试的完整性、有效性以及自动化测试的实施效果&#xff0c;是软件测试成功的重要保证&#xff0c;良好的软件测试用例对于提高测试的有效性和效率至关重要。那大家知道好的测试用例该怎么写吗&#xff1f;应该从哪几个方面来撰写呢&#xff1…

python 基础 -- 安装Python模块

作为一个流行的开源开发项目&#xff0c;Python拥有一个由贡献者和用户组成的活跃支持社区&#xff0c;他们还根据开源许可条款向其他Python开发人员提供他们的软件。 这允许Python用户有效地共享和协作&#xff0c;从其他人已经创建的常见(有时甚至是罕见的!)问题的解决方案中…

Word怎么转换成PDF文档?多个Word转换成PDF步骤分享

word文档是一种非常好用的文件格式&#xff0c;可以帮助用户们很好的保存图片和文字内容&#xff0c;不过并不是只有word这一种文档类文件格式&#xff0c;还有一种pdf文档也深受用户们的欢迎&#xff0c;在工作或者学习过程中这两种文档是可以互相转换格式的&#xff0c;那么W…

【ArcGIS Pro二次开发】(61):样式(Style)和符号(Symbol)

在 ArcGIS Pro SDK 中&#xff0c;地图要素符号&#xff08;Symbol&#xff09;和符号样式&#xff08;Style&#xff09;是2个很重要的概念。 【Symbol】是用于表示地图上不同类型的要素&#xff08;如点、线、面&#xff09;的图形化表示。 在地图中&#xff0c;各种要素都…

Spark项目Java和Scala混合打包编译

文章目录 项目结构Pom完整文件编译查看 实际开发用有时候引用自己写的一些java工具类&#xff0c;但是整个项目是scala开发的spark程序&#xff0c;在项目打包时需要考虑到java和scala混合在一起编译。 今天看到之前很久之前写的一些打包编译文章&#xff0c;发现很多地方不太对…

springboot+docker实现微服务的小例子

【任务】&#xff1a; 创建一个服务A&#xff1a;service_hello 创建一个服务B&#xff1a;service_name service_name负责提供一个api接口返回一个name字符串。 service_hello负责从这个接口获取name字符串&#xff0c;然后进行一个字符串拼接&#xff0c;在后面加一个hello&…