I am new to JavaFX 2.2 and as of now I couldn't find a way to display SVG Images in my JavaFX 2.2 application. I took a look at Batik, but it didn't do the trick for me as it converts to BufferedImages
and not to javafx.ImageView
.
我是JavaFX 2.2的新手,到目前为止,我还无法在JavaFX 2.2应用程序中显示SVG图像。我查看了Batik,但是它并没有为我带来什么好处,因为它会转换到BufferedImages而不是javafx.ImageView。
Is there any way to display an SVG image in an JavaFX application? Or can you at least export an SVG image from JavaFX? Does the function Node.snapshot()
help there in any way?
是否有办法在JavaFX应用程序中显示SVG图像?或者至少可以从JavaFX导出SVG图像?函数Node.snapshot()是否在某种程度上帮助了这一点?
3 个解决方案
#1
39
Is there any way to display an SVG image in an JavaFX application?
是否有办法在JavaFX应用程序中显示SVG图像?
Here are some options:
这里有一些选项:
- Create a WebView and load the svg image into the WebView's WebEngine.
- 创建一个WebView并将svg图像加载到WebView的WebEngine中。
- The e(fx)clipse project includes an svg to fxml converter (link now dead :().
- e(fx)clipse项目包含一个svg到fxml转换器(link now dead:())。
- This NetBeans plugin also converts svg to fxml (link now dead :().
- 这个NetBeans插件还将svg转换为fxml (link now dead:())。
- You can use an awt based library like Batik or svgsalamander and convert the resultant BufferedImage to a JavaFX Image.
- 您可以使用基于awt的库,如Batik或svgsalamander,并将生成的BufferedImage转换为JavaFX映像。
- JavaFX 2.2 natively includes support for some minimal SVGPath strings (not the full SVG spec).
- JavaFX 2.2本机包含对一些最小SVGPath字符串(不是完整的SVG规范)的支持。
- You could write a convertor which renders the svg using JavaFX Canvas GraphicsContext commands.
- 您可以编写一个转换器,使用JavaFX Canvas GraphicsContext命令呈现svg。
- FranzXaver provides an SVGLoader, whose usage is demonstrated in the answer to: Load SVG file in a Button on JavaFX
- FranzXaver提供一个SVGLoader,其用法在以下答案中得到演示:在JavaFX上的一个按钮中加载SVG文件
Or can you at least export an SVG image from javafx?
或者至少可以从javafx导出SVG图像?
This feature sounds like a JavaFX SceneGraph to svg converter. While it is theoretically possible, I am not aware that anybody has created such a tool yet.
这个特性听起来就像从JavaFX场景到svg转换器。虽然这在理论上是可能的,但我还没有意识到有人创造了这样一个工具。
Does the function Node.snapshot() help there in any way?
函数Node.snapshot()是否在某种程度上帮助了这一点?
Node.snapshot() will not help with exporting an svg image from a JavaFX scene graph as svg is a vector based format and a node snapshot is a bit mapped format.
快照()不会帮助从JavaFX场景图导出svg图像,因为svg是基于矢量的格式,节点快照是位映射格式。
I took a look at Batik, but it didn't do the trick for me as it converts to BufferedImages and not to javafx.ImageView.
我查看了Batik,但是它并没有为我带来什么好处,因为它会转换到BufferedImages而不是javafx.ImageView。
You can easily convert between awt BufferedImages and javafx images using SwingFXUtils.
您可以使用SwingFXUtils轻松地在awt BufferedImages和javafx映像之间进行转换。
In terms of performance - which way would you recommend?
就表现而言——你会推荐哪一种方式?
For complex svg's, rather than rendering from fxml, you will probably get better performance rendering to a bitmapped image or canvas graphics context. This is because your scene graph will end up a lot simpler, with far less nodes - which means that the javafx runtime will have a lot less work to do. For simple svgs (< 1000 nodes generated), it probably won't matter too much.
对于复杂的svg,而不是从fxml进行呈现,您可能会获得更好的性能呈现到位图图像或画布图形上下文。这是因为您的场景图将更简单,节点更少——这意味着javafx运行时要做的工作要少得多。对于简单的svgs(生成< 1000个节点),它可能不会太重要。
Is converting an SVG to an FXML about creating instances of javafx.scene.shape.SVGPath?
将SVG转换为FXML是关于创建javafx.scene.shape.SVGPath的实例吗?
Partially. The full SVG specification covers much more ground than the basic shapes. In addition gradients, effects, animations, etc can be performed by an SVG. So if the source SVG image includes those additional items, then they also need to be converted to FXML (as best they can be, there will be some aspects of SVG such as scripting which would be hard to translate to FXML).
部分。完整的SVG规范包含的基础比基本形状多得多。此外,梯度、效果、动画等可以由SVG执行。因此,如果源SVG图像包含这些附加项,那么还需要将它们转换为FXML(最好是这样,SVG的某些方面,比如脚本,很难转换为FXML)。
My guess is that the size and complexity of the SVG specification is one of the reasons why no direct support for the full SVG image system is currently included in the JavaFX core API and, instead, only limited similar functionality such as SVGPath is offered. Implementing SVG natively in the JavaFX core API would have been high cost for relatively little reward when compared to other desirable items.
我的猜测是,SVG规范的大小和复杂性是目前在JavaFX核心API中不包含对完整SVG图像系统的直接支持的原因之一,相反,它只提供了有限的类似功能,比如SVGPath。在JavaFX核心API中本地实现SVG的成本相对于其他理想的项目来说,相对来说是相对较少的。
If that is the case, wouldn't #2 (and #3) and #5 be just the same?
如果是这样,难道2号(和3号)和5号不是一样的吗?
No. The NetBeans and Eclipse tools referenced in #2 and #3 were more functional than just the SVGPath facilities mentioned in #5, as those tools converted additional aspects of the the SVG specification to FXML equivalents (e.g. gradients, effects and transforms).
不。#2和#3中引用的NetBeans和Eclipse工具比#5中提到的SVGPath工具功能更强,因为这些工具将SVG规范的其他方面转换为FXML等价物(例如渐变、效果和转换)。
#2
20
I used the transcoder class above to create a little project on github that adds SVG support to JavaFX (JavaFX 8 though): javafxsvg
我使用上面的transcoder类在github上创建了一个小项目,该项目将SVG支持添加到JavaFX(虽然是JavaFX 8): javafxsvg
After calling
后调用
SvgImageLoaderFactory.install();
you can use SVG images anywhere in your Java code or CSS just like any other supported image type.
您可以在Java代码或CSS中的任何地方使用SVG图像,就像任何其他支持的图像类型一样。
#3
9
JavaFX + Batik + Custom Transcoder
Since I've nowhere found a complete example of using Batik in conjunction with JavaFX, I am providing a complete solution below.
由于我还没有找到与JavaFX一起使用Batik的完整示例,下面我将提供完整的解决方案。
Note that I removed exception handling (e.g. for the TranscoderException
) for brevity.
You can access the full code here: https://gist.github.com/ComFreek/b0684ac324c815232556
注意,为了简洁,我删除了异常处理(例如TranscoderException)。您可以在这里访问完整的代码:https://gist.github.com/ComFreek/b0684ac324c815232556
-
In order to convert a SVG file with Batik to a
BufferedImage
, you have to implement a custom transcoder:为了将一个带有Batik的SVG文件转换为BufferedImage,您必须实现一个定制的代码转换器:
/** * Many thanks to bb-generation for sharing this code! * @author bb-generation * @link http://bbgen.net/blog/2011/06/java-svg-to-bufferedimage/ * @link In case the link above is still down: https://web.archive.org/web/20131215231214/http://bbgen.net/blog/2011/06/java-svg-to-bufferedimage/ */ public class BufferedImageTranscoder extends ImageTranscoder { private BufferedImage img = null; @Override public BufferedImage createImage(int width, int height) { BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); return bi; } @Override public void writeImage(BufferedImage img, TranscoderOutput to) throws TranscoderException { this.img = img; } public BufferedImage getBufferedImage() { return img; } }
-
Use the transcoder to generate a
BufferedImage
object:使用transcoder生成缓冲编辑对象:
BufferedImageTranscoder trans = new BufferedImageTranscoder(); // file may be an InputStream. // Consult Batik's documentation for more possibilities! TranscoderInput transIn = new TranscoderInput(file); trans.transcode(transIn, null);
-
Convert the
BufferedImage
object to anImage
object (from JavaFX):将BufferedImage对象转换为图像对象(来自JavaFX):
// Use WritableImage if you want to further modify the image (by using a PixelWriter) Image img = SwingFXUtils.toFXImage(trans.getBufferedImage(), null);
-
Finally assign the previously received object to your
ImageView
:最后将先前接收到的对象分配给ImageView:
imgView.setImage(img);
#1
39
Is there any way to display an SVG image in an JavaFX application?
是否有办法在JavaFX应用程序中显示SVG图像?
Here are some options:
这里有一些选项:
- Create a WebView and load the svg image into the WebView's WebEngine.
- 创建一个WebView并将svg图像加载到WebView的WebEngine中。
- The e(fx)clipse project includes an svg to fxml converter (link now dead :().
- e(fx)clipse项目包含一个svg到fxml转换器(link now dead:())。
- This NetBeans plugin also converts svg to fxml (link now dead :().
- 这个NetBeans插件还将svg转换为fxml (link now dead:())。
- You can use an awt based library like Batik or svgsalamander and convert the resultant BufferedImage to a JavaFX Image.
- 您可以使用基于awt的库,如Batik或svgsalamander,并将生成的BufferedImage转换为JavaFX映像。
- JavaFX 2.2 natively includes support for some minimal SVGPath strings (not the full SVG spec).
- JavaFX 2.2本机包含对一些最小SVGPath字符串(不是完整的SVG规范)的支持。
- You could write a convertor which renders the svg using JavaFX Canvas GraphicsContext commands.
- 您可以编写一个转换器,使用JavaFX Canvas GraphicsContext命令呈现svg。
- FranzXaver provides an SVGLoader, whose usage is demonstrated in the answer to: Load SVG file in a Button on JavaFX
- FranzXaver提供一个SVGLoader,其用法在以下答案中得到演示:在JavaFX上的一个按钮中加载SVG文件
Or can you at least export an SVG image from javafx?
或者至少可以从javafx导出SVG图像?
This feature sounds like a JavaFX SceneGraph to svg converter. While it is theoretically possible, I am not aware that anybody has created such a tool yet.
这个特性听起来就像从JavaFX场景到svg转换器。虽然这在理论上是可能的,但我还没有意识到有人创造了这样一个工具。
Does the function Node.snapshot() help there in any way?
函数Node.snapshot()是否在某种程度上帮助了这一点?
Node.snapshot() will not help with exporting an svg image from a JavaFX scene graph as svg is a vector based format and a node snapshot is a bit mapped format.
快照()不会帮助从JavaFX场景图导出svg图像,因为svg是基于矢量的格式,节点快照是位映射格式。
I took a look at Batik, but it didn't do the trick for me as it converts to BufferedImages and not to javafx.ImageView.
我查看了Batik,但是它并没有为我带来什么好处,因为它会转换到BufferedImages而不是javafx.ImageView。
You can easily convert between awt BufferedImages and javafx images using SwingFXUtils.
您可以使用SwingFXUtils轻松地在awt BufferedImages和javafx映像之间进行转换。
In terms of performance - which way would you recommend?
就表现而言——你会推荐哪一种方式?
For complex svg's, rather than rendering from fxml, you will probably get better performance rendering to a bitmapped image or canvas graphics context. This is because your scene graph will end up a lot simpler, with far less nodes - which means that the javafx runtime will have a lot less work to do. For simple svgs (< 1000 nodes generated), it probably won't matter too much.
对于复杂的svg,而不是从fxml进行呈现,您可能会获得更好的性能呈现到位图图像或画布图形上下文。这是因为您的场景图将更简单,节点更少——这意味着javafx运行时要做的工作要少得多。对于简单的svgs(生成< 1000个节点),它可能不会太重要。
Is converting an SVG to an FXML about creating instances of javafx.scene.shape.SVGPath?
将SVG转换为FXML是关于创建javafx.scene.shape.SVGPath的实例吗?
Partially. The full SVG specification covers much more ground than the basic shapes. In addition gradients, effects, animations, etc can be performed by an SVG. So if the source SVG image includes those additional items, then they also need to be converted to FXML (as best they can be, there will be some aspects of SVG such as scripting which would be hard to translate to FXML).
部分。完整的SVG规范包含的基础比基本形状多得多。此外,梯度、效果、动画等可以由SVG执行。因此,如果源SVG图像包含这些附加项,那么还需要将它们转换为FXML(最好是这样,SVG的某些方面,比如脚本,很难转换为FXML)。
My guess is that the size and complexity of the SVG specification is one of the reasons why no direct support for the full SVG image system is currently included in the JavaFX core API and, instead, only limited similar functionality such as SVGPath is offered. Implementing SVG natively in the JavaFX core API would have been high cost for relatively little reward when compared to other desirable items.
我的猜测是,SVG规范的大小和复杂性是目前在JavaFX核心API中不包含对完整SVG图像系统的直接支持的原因之一,相反,它只提供了有限的类似功能,比如SVGPath。在JavaFX核心API中本地实现SVG的成本相对于其他理想的项目来说,相对来说是相对较少的。
If that is the case, wouldn't #2 (and #3) and #5 be just the same?
如果是这样,难道2号(和3号)和5号不是一样的吗?
No. The NetBeans and Eclipse tools referenced in #2 and #3 were more functional than just the SVGPath facilities mentioned in #5, as those tools converted additional aspects of the the SVG specification to FXML equivalents (e.g. gradients, effects and transforms).
不。#2和#3中引用的NetBeans和Eclipse工具比#5中提到的SVGPath工具功能更强,因为这些工具将SVG规范的其他方面转换为FXML等价物(例如渐变、效果和转换)。
#2
20
I used the transcoder class above to create a little project on github that adds SVG support to JavaFX (JavaFX 8 though): javafxsvg
我使用上面的transcoder类在github上创建了一个小项目,该项目将SVG支持添加到JavaFX(虽然是JavaFX 8): javafxsvg
After calling
后调用
SvgImageLoaderFactory.install();
you can use SVG images anywhere in your Java code or CSS just like any other supported image type.
您可以在Java代码或CSS中的任何地方使用SVG图像,就像任何其他支持的图像类型一样。
#3
9
JavaFX + Batik + Custom Transcoder
Since I've nowhere found a complete example of using Batik in conjunction with JavaFX, I am providing a complete solution below.
由于我还没有找到与JavaFX一起使用Batik的完整示例,下面我将提供完整的解决方案。
Note that I removed exception handling (e.g. for the TranscoderException
) for brevity.
You can access the full code here: https://gist.github.com/ComFreek/b0684ac324c815232556
注意,为了简洁,我删除了异常处理(例如TranscoderException)。您可以在这里访问完整的代码:https://gist.github.com/ComFreek/b0684ac324c815232556
-
In order to convert a SVG file with Batik to a
BufferedImage
, you have to implement a custom transcoder:为了将一个带有Batik的SVG文件转换为BufferedImage,您必须实现一个定制的代码转换器:
/** * Many thanks to bb-generation for sharing this code! * @author bb-generation * @link http://bbgen.net/blog/2011/06/java-svg-to-bufferedimage/ * @link In case the link above is still down: https://web.archive.org/web/20131215231214/http://bbgen.net/blog/2011/06/java-svg-to-bufferedimage/ */ public class BufferedImageTranscoder extends ImageTranscoder { private BufferedImage img = null; @Override public BufferedImage createImage(int width, int height) { BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); return bi; } @Override public void writeImage(BufferedImage img, TranscoderOutput to) throws TranscoderException { this.img = img; } public BufferedImage getBufferedImage() { return img; } }
-
Use the transcoder to generate a
BufferedImage
object:使用transcoder生成缓冲编辑对象:
BufferedImageTranscoder trans = new BufferedImageTranscoder(); // file may be an InputStream. // Consult Batik's documentation for more possibilities! TranscoderInput transIn = new TranscoderInput(file); trans.transcode(transIn, null);
-
Convert the
BufferedImage
object to anImage
object (from JavaFX):将BufferedImage对象转换为图像对象(来自JavaFX):
// Use WritableImage if you want to further modify the image (by using a PixelWriter) Image img = SwingFXUtils.toFXImage(trans.getBufferedImage(), null);
-
Finally assign the previously received object to your
ImageView
:最后将先前接收到的对象分配给ImageView:
imgView.setImage(img);