【问题标题】:SVG Image in JavaFX 2.2JavaFX 2.2 中的 SVG 图像
【发布时间】:2012-09-08 07:30:05
【问题描述】:

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

有没有办法在 JavaFX 应用程序中显示 SVG 图像?或者您至少可以从 JavaFX 导出 SVG 图像吗?函数Node.snapshot() 有什么帮助吗?

【问题讨论】:

    标签: svg javafx batik


    【解决方案1】:

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

    这里有一些选项:

    1. WebViewload 的svg 图像创建到WebView 的WebEngine 中。
    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

    或者您至少可以从 javafx 导出 SVG 图像吗?

    此功能听起来像是 JavaFX SceneGraph 到 svg 的转换器。虽然理论上是可行的,但我不知道有人已经创建了这样的工具。

    函数 Node.snapshot() 有什么帮助吗?

    Node.snapshot() 无法从 JavaFX 场景图中导出 svg 图像,因为 svg 是基于矢量的格式,而节点快照是位映射格式。

    我查看了 Batik,但它并没有为我解决问题,因为它转换为 BufferedImages 而不是 javafx.ImageView。

    您可以使用 SwingFXUtils 在 awt BufferedImages 和 javafx 图像之间轻松转换。

    在性能方面 - 您会推荐哪种方式?

    对于复杂的 svg,而不是从 fxml 渲染,您可能会获得更好的性能渲染到位图图像或画布图形上下文。这是因为您的场景图最终会变得更简单,节点更少——这意味着 javafx 运行时要做的工作会少得多。对于简单的 svg(生成

    关于创建 javafx.scene.shape.SVGPath 实例是否将 SVG 转换为 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 等效项(例如渐变、效果和转换)。

    【讨论】:

    • 感谢您的详细解答!在性能方面 - 您会推荐哪种方式?将它们全部转换为 fxml?
    • 谢谢!我想投票支持你的答案,但我没有这样做的声誉。对不起!
    • @jewelsea 是否正在将 SVG 转换为 FXML,以创建 javafx.scene.shape.SVGPath 的实例?如果是这样的话,#2(和#3)和#5不是一样吗?或者你在#5 中提到了不同的SVGPath? (编辑:显然它与我看到的链接相同。所以我宁愿问#2 和#3 中的那些是否与javafx.scene.shape.SVGPath 无关。)我正在看这个例子:raw.githubusercontent.com/usander/e-fx-clipse/master/…
    【解决方案2】:

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

    调用后

    SvgImageLoaderFactory.install();
    

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

    【讨论】:

    • 这个解决方案的问题是它依赖于蜡染,蜡染已经损坏并且没有迹象表明很快就会被修复。
    【解决方案3】:

    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);
      

    【讨论】:

    • Batik 已经在 J​​ava9+ 上被破坏了几年了,维护者似乎对修复它不太感兴趣,所以如果你需要在过去 5 年发布的 JRE 上运行,它将追求这种方法是浪费时间。有关详细信息,请参阅issues.apache.org/jira/browse/BATIK-1260。结合厨房水槽非可选依赖项,这些依赖项遮蔽了常见的 api jar - 例如 jython - 我不建议在生产代码中使用 Batik。
    【解决方案4】:

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

    有一些方法可以生成 JavaFX 节点树,还有其他方法可以生成图像。

    主类也叫SVGLoader,但是这个库是自包含的。当然,它可能不支持 Batik 的完整扩展。

    【讨论】:

      【解决方案5】:

      使用 Web 视图。下面是一个加载 SVG 的工作示例,支持 CSS 动画:

      • 控制器类SplashController.java:

        public class SplashController implements Initializable {
              @FXML
              private StackPane rootPane;
              @FXML private WebView webView; 
              private WebEngine webEngine; 
                  public void initialize(URL url, ResourceBundle rb) {
                   webEngine = webView.getEngine();
                    URL url1 = getClass().getResource("/android_switch_string.svg");
                    webEngine.load(url1.toExternalForm());
                  }
          }
        
      • 资源文件 splash_svg.fxml:

        < StackPane fx:id="rootPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="360.0" prefWidth="508.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="diagnosticsWin.SplashController">
                <children>
                  <WebView fx:id="webView" prefHeight="200.0" prefWidth="200.0" />
                </children>
              </StackPane>
        

      完整代码说明https://www.ap-impulse.com/splash-screen-and-javafx-statya-106/

      项目https://github.com/nik137/Diagnostics

      【讨论】:

        猜你喜欢
        • 2015-04-13
        • 1970-01-01
        • 2017-04-22
        • 2012-10-04
        • 1970-01-01
        • 2012-09-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多