我是JavaFX 2.2的新手,到目前为止,我找不到在JavaFX 2.2应用程序中显示SVG图像的方法。我看了看Batik,但它并没有为我做这个伎俩,因为它转换为BufferedImages
而不是javafx.ImageView
。
有没有办法在JavaFX应用程序中显示SVG图像?或者你至少可以从JavaFX导出SVG图像?函数Node.snapshot()
是否以任何方式帮助那里?
答案 0 :(得分:43)
有没有办法在JavaFX应用程序中显示SVG图像?
以下是一些选项:
或者至少可以从javafx导出SVG图像吗?
此功能听起来像是一个JavaFX SceneGraph到svg转换器。虽然理论上可行,但我还没有意识到还有人创造了这样的工具。
函数Node.snapshot()是否以任何方式帮助它?
Node.snapshot()无法帮助从JavaFX场景图导出svg图像,因为svg是基于矢量的格式,而节点快照是位映射格式。
我看了一下Batik,但它没有为我做这个技巧,因为它转换为BufferedImages而不是javafx.ImageView。
您可以使用SwingFXUtils在awt BufferedImages和javafx图像之间轻松转换。
在表现方面 - 您会推荐哪种方式?
对于复杂的svg,而不是从fxml渲染,您可能会获得更好的性能渲染到位图图像或画布图形上下文。这是因为你的场景图最终会更简单,节点也少得多 - 这意味着javafx运行时的工作量要少得多。对于简单的svgs(生成<1000个节点),它可能无关紧要。
是否正在将SVG转换为关于创建javafx.scene.shape.SVGPath实例的FXML?
部分。完整SVG specification比基本形状覆盖更多的地面。此外,SVG可以执行渐变,效果,动画等。因此,如果源SVG图像包含那些附加项,那么它们也需要转换为FXML(尽管它们可能是最好的,SVG的某些方面,例如脚本很难转换为FXML)。
我的猜测是SVG规范的大小和复杂性是JavaFX核心API当前不包含对完整SVG图像系统的直接支持的原因之一,而是仅有限的类似功能,例如SVGPath提供。与其他理想项目相比,在JavaFX核心API中本地实现SVG的成本相对较低,而且奖励相对较少。
如果是这种情况,#2(和#3)和#5不一样吗?
没有。 #2和#3中引用的NetBeans和Eclipse工具比#5中提到的SVGPath工具更具功能性,因为这些工具将SVG规范的其他方面转换为FXML等效项(例如渐变,效果和变换)。 p>
答案 1 :(得分:23)
我使用上面的代码转换器类在github上创建了一个小项目,它为JavaFX添加了SVG支持(尽管JavaFX 8):javafxsvg
致电后
SvgImageLoaderFactory.install();
您可以在Java代码或CSS中的任何位置使用SVG图像,就像任何其他支持的图像类型一样。
答案 2 :(得分:9)
由于我没有找到将Batik与JavaFX结合使用的完整示例,因此我在下面提供了完整的解决方案。
请注意,为简洁起见,我删除了异常处理(例如TranscoderException
)
您可以在此处访问完整代码:https://gist.github.com/ComFreek/b0684ac324c815232556
要将带有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;
}
}
使用代码转换器生成BufferedImage
对象:
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);
将BufferedImage
对象转换为Image
对象(来自JavaFX):
// Use WritableImage if you want to further modify the image (by using a PixelWriter)
Image img = SwingFXUtils.toFXImage(trans.getBufferedImage(), null);
最后将以前收到的对象分配给ImageView
:
imgView.setImage(img);
答案 3 :(得分:0)
我不想使用需要蜡染的库,所以我在这里开发了一个没有依赖项的小库:https://github.com/hervegirod/fxsvgimage
有生成 JavaFX 节点树的方法,也有生成图像的方法。
主类也被命名为 SVGLoader
,但这个库是自包含的。当然,它可能不支持 Batik 的全部扩展。