我对JavaFX 2.2还不熟悉,目前我找不到在JavaFX 2.2应用程序中显示SVG图像的方法。我查看了Batik,但它没能为我完成任务,因为它将SVG转换为BufferedImages
而不是javafx.ImageView
。
有没有办法在JavaFX应用程序中显示SVG图像?或者你至少能从JavaFX导出SVG图像吗?Node.snapshot()
函数是否有帮助?
或者你能否至少从JavaFX中导出SVG图像?
这个功能听起来像是JavaFX场景图到svg转换器。虽然在理论上是可能的,但我不知道是否已经有人创建了这样的工具。
函数Node.snapshot()能帮助吗?
Node.snapshot()对于从JavaFX场景图导出svg图像没有帮助,因为svg是一种基于矢量的格式,而节点快照是一种位图格式。
我看了一下Batik,但它不能将图像转换为javafx.ImageView,只能转换为BufferedImages。
您可以使用SwingFXUtils轻松地在awt BufferedImages和javafx images之间进行转换。
对于复杂的SVG图形,与其从FXML渲染,您可能会获得更好的性能,将其渲染为位图图像或画布图形上下文。这是因为您的场景图将变得简单得多,节点要少得多,这意味着JavaFX运行时需要做的工作要少得多。对于简单的SVG(< 1000个生成的节点),这可能不太重要。就性能而言,你会推荐哪种方式?
不是。在#2和#3中引用的NetBeans和Eclipse工具比#5中提到的SVGPath功能更加功能强大,因为这些工具将SVG规范的其他方面转换为FXML等效项(例如渐变,效果和变换)。如果是这样,那么#2(和#3)和#5不是一样的吗?
我使用上述转码器类在Github上创建了一个小项目,该项目为JavaFX(JavaFX 8)添加了SVG支持:javafxsvg
在调用后,
SvgImageLoaderFactory.install();
您可以像使用任何其他支持的图像类型一样,在Java代码或CSS中的任何地方使用SVG图像。
由于我没有找到一个完整的示例来展示如何将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);
我不想使用需要batik的库,所以我开发了一个没有依赖关系的小型库,链接在这里:https://github.com/hervegirod/fxsvgimage
它有生成JavaFX节点树的方法和生成图像的方法。
主要类也被命名为SVGLoader
,但这个库是自包含的。当然,它可能不支持完整的Batik功能。
控制器类 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/
javafx.scene.shape.SVGPath
实例吗?如果是这样,那么#2(和#3)和#5不是完全相同吗?或者你在#5中提到了另一个SVGPath
?(编辑:显然它与我看到的链接相同。所以我更想问#2和#3是否与javafx.scene.shape.SVGPath
无关。)我正在查看此示例:https://raw.githubusercontent.com/usander/e-fx-clipse/master/at.bestsolution.efxclipse.formats.svg/samples/application-exit.fxml - konsolebox