web-dev-qa-db-fra.com

Image SVG dans JavaFX 2.2

Je suis nouveau sur JavaFX 2.2 et pour l'instant je n'ai pas trouvé de moyen d'afficher les images SVG dans mon application JavaFX 2.2. J'ai jeté un œil à Batik, mais il n'a pas fait l'affaire pour moi car il se convertit en BufferedImages et non en javafx.ImageView.

Existe-t-il un moyen d'afficher une image SVG dans une application JavaFX? Ou pouvez-vous au moins exporter une image SVG depuis JavaFX? La fonction Node.snapshot() y aide-t-elle de quelque façon?

27
user1582432

Existe-t-il un moyen d'afficher une image SVG dans une application JavaFX?

Voici quelques options:

  1. Créez un WebView et load l'image svg dans le WebEngine de WebView.
  2. Le projet e (fx) clipse comprend un convertisseur svg en fxml (lien maintenant mort :().
  3. Ce plugin NetBeans convertit également svg en fxml (lien maintenant mort :().
  4. Vous pouvez utiliser une bibliothèque basée sur awt comme Batik ou svgsalamander et convertir le BufferedImage résultant en une image JavaFX.
  5. JavaFX 2.2 inclut nativement la prise en charge de certaines chaînes minimales SVGPath (pas la spécification SVG complète).
  6. Vous pouvez écrire un convertisseur qui rend le svg en utilisant les commandes JavaFX Canvas GraphicsContext .
  7. FranzXaver fournit un SVGLoader, dont l'utilisation est démontrée dans la réponse à: Charger le fichier SVG dans un bouton sur JavaFX

Ou pouvez-vous au moins exporter une image SVG depuis javafx?

Cette fonctionnalité ressemble à un convertisseur JavaFX SceneGraph en svg. Bien que cela soit théoriquement possible, je ne suis pas au courant que quiconque ait encore créé un tel outil.

La fonction Node.snapshot () y aide-t-elle en aucune façon?

Node.snapshot () n'aidera pas à exporter une image svg à partir d'un graphe de scène JavaFX car svg est un format vectoriel et un instantané de nœud est un format bitmap.

J'ai jeté un coup d'œil à Batik, mais cela n'a pas fait l'affaire pour moi car il se convertit en BufferedImages et non en javafx.ImageView.

Vous pouvez facilement convertir entre les images awt BufferedImages et javafx en utilisant SwingFXUtils .

En termes de performances - quelle voie recommanderiez-vous?

Pour les svg complexes, plutôt que le rendu à partir de fxml, vous obtiendrez probablement un meilleur rendu des performances dans une image bitmap ou un contexte graphique de canevas. En effet, votre graphique de scène se terminera beaucoup plus simplement, avec beaucoup moins de nœuds - ce qui signifie que le runtime javafx aura beaucoup moins de travail à faire. Pour les svgs simples (<1000 nœuds générés), cela n'aura probablement pas trop d'importance.

La conversion d'un SVG en FXML concerne-t-elle la création d'instances de javafx.scene.shape.SVGPath?

Partiellement. La pleine spécification SVG couvre beaucoup plus de terrain que les formes de base. De plus, les dégradés, les effets, les animations, etc. peuvent être exécutés par un SVG. Donc, si l'image SVG source comprend ces éléments supplémentaires, ils doivent également être convertis en FXML (dans la mesure du possible, il y aura certains aspects de SVG tels que les scripts qui seraient difficiles à traduire en FXML).

Je suppose que la taille et la complexité de la spécification SVG sont l'une des raisons pour lesquelles aucune prise en charge directe du système d'image SVG complet n'est actuellement incluse dans l'API JavaFX de base et, à la place, seules des fonctionnalités similaires limitées telles que SVGPath sont proposées. L'implémentation native de SVG dans l'API JavaFX aurait coûté cher pour une récompense relativement faible par rapport à d'autres éléments souhaitables.

Si tel est le cas, les numéros 2 (et 3) et 5 ne seraient-ils pas les mêmes?

Non. Les outils NetBeans et Eclipse référencés dans # 2 et # 3 étaient plus fonctionnels que les installations SVGPath mentionnées dans # 5, car ces outils convertissaient des aspects supplémentaires de la spécification SVG en équivalents FXML (par exemple les gradients, les effets et les transformations).

43
jewelsea

J'ai utilisé la classe de transcodeur ci-dessus pour créer un petit projet sur github qui ajoute le support SVG à JavaFX (JavaFX 8 cependant): javafxsvg

Après avoir appelé

SvgImageLoaderFactory.install();

vous pouvez utiliser des images SVG n'importe où dans votre Java ou CSS, comme tout autre type d'image pris en charge.

24
Jan Gassen

Transcodeur JavaFX + Batik + personnalisé

Comme je n'ai trouvé nulle part un exemple complet d'utilisation de Batik en conjonction avec JavaFX, je fournis une solution complète ci-dessous.

Notez que j'ai supprimé la gestion des exceptions (par exemple pour le TranscoderException) par souci de concision.
Vous pouvez accéder au code complet ici: https://Gist.github.com/ComFreek/b0684ac324c815232556 =

  1. Pour convertir un fichier SVG avec Batik en BufferedImage, vous devez implémenter un transcodeur personnalisé:

    /**
     * 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. Utilisez le transcodeur pour générer un objet 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. Convertissez l'objet BufferedImage en un objet Image (à partir de JavaFX):

    // Use WritableImage if you want to further modify the image (by using a PixelWriter)
    Image img = SwingFXUtils.toFXImage(trans.getBufferedImage(), null);
    
  4. Enfin, affectez l'objet précédemment reçu à votre ImageView:

    imgView.setImage(img);
    
9
ComFreek