JavaFX 2.2中的SVG图像

use*_*432 27 svg javafx batik

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

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

jew*_*sea 44

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

以下是一些选项:

  1. 创建WebView并将svg图像加载到WebView的WebEngine中.
  2. E(FX)clipse项目包括SVG至FXML转换器(链接已经死了:().
  3. NetBeans插件还将svg转换为fxml(link now dead :().
  4. 您可以使用基于awt的库(如Batiksvgsalamander),并将生成的BufferedImage转换为JavaFX Image.
  5. JavaFX 2.2本身包含对一些最小SVGPath字符串的支持(不是完整的SVG规范).
  6. 您可以编写一个转换器,使用JavaFX Canvas GraphicsContext命令呈现svg .
  7. FranzXaver提供了一个SVGLoader,其用法在以下答案中得到证明:在JavaFX上的Button中加载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规范比基本形状覆盖更多的地面.此外,SVG可以执行渐变,效果,动画等.因此,如果源SVG图像包含那些附加项,那么它们也需要转换为FXML(尽管它们可能是最好的,SVG的某些方面,例如脚本很难转换为FXML).

我的猜测是SVG规范的大小和复杂性是JavaFX核心API当前不包含对完整SVG图像系统的直接支持的原因之一,而是仅提供有限的类似功能,例如SVGPath.与其他理想项目相比,在JavaFX核心API中本地实现SVG的成本相对较低.

如果是这种情况,那么#2(和#3)和#5会不一样?

否.#2和#3中引用的NetBeans和Eclipse工具比#5中提到的SVGPath工具更具功能性,因为这些工具将SVG规范的其他方面转换为FXML等效项(例如渐变,效果和变换).


Jan*_*sen 26

我使用上面的代码转换器类在github上创建了一个小项目,它为JavaFX添加了SVG支持(JavaFX 8):javafxsvg

打电话后

SvgImageLoaderFactory.install();
Run Code Online (Sandbox Code Playgroud)

您可以在Java代码或CSS中的任何位置使用SVG图像,就像任何其他支持的图像类型一样.

  • 这个解决方案的问题在于它依赖于蜡染,蜡染已经损坏并且没有迹象表明很快就会被修复。 (2认同)

Com*_*eek 10

JavaFX + Batik + Custom Transcoder

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

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

  1. 要将带有Batik的SVG文件转换为a 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;
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  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);
    
    Run Code Online (Sandbox Code Playgroud)
  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);
    
    Run Code Online (Sandbox Code Playgroud)
  4. 最后将以前收到的对象分配给您ImageView:

    imgView.setImage(img);
    
    Run Code Online (Sandbox Code Playgroud)

  • Batik 在 Java9+ 上已经损坏了几年,维护者似乎对修复它不太感兴趣,因此如果您需要在过去 5 年发布的 JRE 上运行,那么采用这种方法将是浪费时间。有关详细信息,请参阅 https://issues.apache.org/jira/browse/BATIK-1260。与厨房水槽非可选依赖项相结合,这些依赖项遮盖了常见的 api jars - 例如 jython - 我根本不建议在生产代码中使用 Batik。 (2认同)