原文地址: JavaFx 生成二维码工具类封装 - Stars-One的杂货小窝
之前星之音乐下载器有需要生成二维码功能,当时用的是一个开源库来实现的,但是没过多久,发现那个库依赖太多,有个http-client的依赖,把软件都搞大了一倍,而且有时候开发的时候下载依赖还报错,就想换个方案
于是在网上找了下解决方案,最终只需要依赖两个zxing的两个依赖即可实现功能
本文基于TornadoFx框架进行编写,封装工具代码是kotlin版本,工具类已经封装在common-controls库中
工具支持带logo图标,带底部文本的二维码生成
<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>
由于工具代码过多不便阅读,就先讲些使用,工具代码就放下面了
比较核心的就两个方法,如下面代码所示,其他的方法是带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
}
}
}
/**
* 二维码生成工具类
* 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()
}
}
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',
我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A
我是Rails的新手,所以请原谅简单的问题。我正在为一家公司创建一个网站。那家公司想在网站上展示它的客户。我想让客户自己管理这个。我正在为“客户”生成一个表格,我想要的三列是:公司名称、公司描述和Logo。对于名称,我使用的是name:string但不确定如何在脚本/生成脚手架终端命令中最好地创建描述列(因为我打算将其设置为文本区域)和图片。我怀疑描述(我想成为一个文本区域)应该仍然是描述:字符串,然后以实际形式进行调整。不确定如何处理图片字段。那么……说来话长:我在脚手架命令中输入什么来生成描述和图片列? 最佳答案 对于“文本”数
我正在使用RubyonRails3.0.9,我想生成一个传递一些自定义参数的link_toURL。也就是说,有一个articles_path(www.my_web_site_name.com/articles)我想生成如下内容:link_to'Samplelinktitle',...#HereIshouldimplementthecode#=>'http://www.my_web_site_name.com/articles?param1=value1¶m2=value2&...我如何编写link_to语句“alàRubyonRailsWay”以实现该目的?如果我想通过传递一些
有这些railscast。http://railscasts.com/episodes/218-making-generators-in-rails-3有了这个,你就会知道如何创建样式表和脚手架生成器。http://railscasts.com/episodes/216-generators-in-rails-3通过这个,您可以了解如何添加一些文件来修改脚手架View。我想把两者结合起来。我想创建一个生成器,它也可以创建脚手架View。有点像RyanBates漂亮的生成器或web_app_themegem(https://github.com/pilu/web-app-theme)。我
导读语言模型给我们的生产生活带来了极大便利,但同时不少人也利用他们从事作弊工作。如何规避这些难辨真伪的文字所产生的负面影响也成为一大难题。在3月9日智源Live第33期活动「DetectGPT:判断文本是否为机器生成的工具」中,主讲人Eric为我们讲解了DetectGPT工作背后的思路——一种基于概率曲率检测的用于检测模型生成文本的工具,它可以帮助我们更好地分辨文章的来源和可信度,对保护信息真实、防止欺诈等方面具有重要意义。本次报告主要围绕其功能,实现和效果等展开。(文末点击“阅读原文”,查看活动回放。)Ericmitchell斯坦福大学计算机系四年级博士生,由ChelseaFinn和Chri
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,