JavaFX 2.2中的SVG图像

时间:2012-09-15 09:44:04

标签: svg javafx batik

我是JavaFX 2.2的新手,到目前为止,我找不到在JavaFX 2.2应用程序中显示SVG图像的方法。我看了看Batik,但它并没有为我做这个伎俩,因为它转换为BufferedImages而不是javafx.ImageView

有没有办法在JavaFX应用程序中显示SVG图像?或者你至少可以从JavaFX导出SVG图像?函数Node.snapshot()是否以任何方式帮助那里?

4 个答案:

答案 0 :(得分:43)

  

有没有办法在JavaFX应用程序中显示SVG图像?

以下是一些选项:

  1. 在WebView的WebEngine中创建WebViewload svg图像。
  2. e(fx)clipse项目包含svg to fxml converter(链接现已死亡:()。
  3. NetBeans plugin也将svg转换为fxml(链接现已死:()。
  4. 您可以使用基于awt的库,如Batiksvgsalamander,并将生成的BufferedImage转换为JavaFX图像。
  5. JavaFX 2.2本身包含对一些最小SVGPath字符串的支持(不是完整的SVG规范)。
  6. 您可以编写一个转换器,使用JavaFX Canvas GraphicsContext命令呈现svg。
  7. FranzXaver提供了一个SVGLoader,其用法在以下答案中得到了证明:Load SVG file in a Button on JavaFX
  8.   

    或者至少可以从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)

JavaFX + Batik +自定义转码器

由于我没有找到将Batik与JavaFX结合使用的完整示例,因此我在下面提供了完整的解决方案。

请注意,为简洁起见,我删除了异常处理(例如TranscoderException) 您可以在此处访问完整代码https://gist.github.com/ComFreek/b0684ac324c815232556

  1. 要将带有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;
        }
    }
    
  2. 使用代码转换器生成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);
    
  3. BufferedImage对象转换为Image对象(来自JavaFX):

    // Use WritableImage if you want to further modify the image (by using a PixelWriter)
    Image img = SwingFXUtils.toFXImage(trans.getBufferedImage(), null);
    
  4. 最后将以前收到的对象分配给ImageView

    imgView.setImage(img);
    

答案 3 :(得分:0)

我不想使用需要蜡染的库,所以我在这里开发了一个没有依赖项的小库:https://github.com/hervegirod/fxsvgimage

有生成 JavaFX 节点树的方法,也有生成图像的方法。

主类也被命名为 SVGLoader,但这个库是自包含的。当然,它可能不支持 Batik 的全部扩展。