Zephyr
Zephyr

Reputation: 10263

How to use a FontAwesomeIconView object as a Stage's icon?

I am using FontAwesomeFX for many icons throughout my application. I would like to use them as icons for my Stage as well.

Since FontAwesomeIconView extends GlyphIcon which extends Text, I can not use it as an Image directly.

Is there a way to create a usable Image from a Text object?

I have tried to use snapshot, but I am not familiar with that method and end up with the standard "empty" icon on my stage.

Here is the MCVE I have so far:

import de.jensd.fx.glyphs.fontawesome.FontAwesomeIcon;
import de.jensd.fx.glyphs.fontawesome.FontAwesomeIconView;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class FontAwesomeIconExample extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {

        // Simple Interface
        VBox root = new VBox(10);
        root.setAlignment(Pos.CENTER);
        root.setPadding(new Insets(10));

        // Convert the FontAwesomeIconView node to an Image
        FontAwesomeIconView iconView = new FontAwesomeIconView(FontAwesomeIcon.ID_CARD_ALT);
        WritableImage icon = iconView.snapshot(new SnapshotParameters(), null);

        primaryStage.getIcons().add(icon);

        // Show the stage
        primaryStage.setWidth(300);
        primaryStage.setHeight(100);
        primaryStage.setScene(new Scene(root));
        primaryStage.setTitle("Sample");
        primaryStage.show();
    }
}

And the result:

screenshot


Is it possible to use a node snapshot as a stage icon? Or is there a better method of converting the FontAwesomeIconView for this purpose?

EDIT:

I have tried both Sedrick's and JKostikiadis's methods and both give similar results for me.


Sedrick's:

    // Convert the FontAwesomeIconView node to an Image
    FontAwesomeIconView iconView = new FontAwesomeIconView(FontAwesomeIcon.AMAZON);
    WritableImage icon = iconView.snapshot(new SnapshotParameters(), null);
    java.awt.image.BufferedImage bImage = SwingFXUtils.fromFXImage(icon, null);
    ByteArrayOutputStream s = new ByteArrayOutputStream();
    try {
        javax.imageio.ImageIO.write(bImage, "png", s);
    } catch (IOException e) {
        e.printStackTrace();
    }

screenshot


JKostikiadis's:

    FontAwesomeIconView iconView = new FontAwesomeIconView(FontAwesomeIcon.AMAZON);
    WritableImage writableImg = iconView.snapshot(null, null);
    Image img = SwingFXUtils.toFXImage(SwingFXUtils.fromFXImage(writableImg, null), null);
    primaryStage.getIcons().add(img);

screenshot


I believe they both accomplish essentially the same thing (with the sizing of the Image resulting in different displayed icons).

What I do not understand now, is why this is the icon it is producing for me and not them...

I am running Windows 7 and JDK 1.8.0_161.

Upvotes: 4

Views: 3354

Answers (2)

JKostikiadis
JKostikiadis

Reputation: 2917

In addition to Sedrick's answer, another (shorter) solution could be to just create an Image (javafx package) and add it stage icons :

FontAwesomeIconView iconView = new FontAwesomeIconView(FontAwesomeIcon.AMAZON);
WritableImage writableImg = iconView.snapshot(null, null);
Image img = SwingFXUtils.toFXImage(SwingFXUtils.fromFXImage(writableImg, null), null);
primaryStage.getIcons().add(img);

P.S A relative post could be found here : Snapshot Image can't be used as stage icon

Edit:

For some reason, the version 8.15 of the FontawesomeFx require the FontAwesomeIconView to be added on a Scene in order to initialize its content, something that is not necessary to do on the newest version of FontawesomeFx. So, in my opinion, you have to either upgrade your FontawesomeFx version or to add the FontAwesomeIconView on a Scene and after to take the snapshot. Like this :

FontAwesomeIconView iconView = new FontAwesomeIconView(FontAwesomeIcon.ID_CARD_ALT);
Scene scene = new Scene(new StackPane(iconView));
WritableImage writableImg = iconView.snapshot(null, null);
Image img = SwingFXUtils.toFXImage(SwingFXUtils.fromFXImage(writableImg, null), null);

Here is the result (using 8.5 version):

enter image description here

Upvotes: 2

SedJ601
SedJ601

Reputation: 13858

I just figured it out. The goal is to get an InputStream. I was able to do that using SwingFXUtils.fromFXImage(icon, null); to get a bufferedImage. From there I used ImageIO.write(bImage, "png", s); to get a byte array. I used to byte array to get an InputStream.

import de.jensd.fx.glyphs.fontawesome.FontAwesomeIcon;
import de.jensd.fx.glyphs.fontawesome.FontAwesomeIconView;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.image.Image;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javax.imageio.ImageIO;

public class FontAwesomeIconExample extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {

        try {
            // Simple Interface
            VBox root = new VBox(10);
            root.setAlignment(Pos.CENTER);
            root.setPadding(new Insets(10));

            // Convert the FontAwesomeIconView node to an Image
            FontAwesomeIconView iconView = new FontAwesomeIconView(FontAwesomeIcon.AMAZON);
            WritableImage icon = iconView.snapshot(new SnapshotParameters(), null);
            BufferedImage bImage = SwingFXUtils.fromFXImage(icon, null);
            ByteArrayOutputStream s = new ByteArrayOutputStream();
            ImageIO.write(bImage, "png", s);
            InputStream is = new ByteArrayInputStream(s.toByteArray());

            primaryStage.getIcons().add(new Image(is, 16, 16, false, false));

            // Show the stage
            primaryStage.setWidth(300);
            primaryStage.setHeight(100);
            primaryStage.setScene(new Scene(root));
            primaryStage.setTitle("Sample");
            primaryStage.show();
        } catch (IOException ex) {
            Logger.getLogger(FontAwesomeIconExample.class.getName()).log(Level.SEVERE, null, ex);
        }
    }    
}

enter image description here enter image description here

This is worth noting from the javadoc.

The images should be different sizes of the same image and the best size will be chosen, eg. 16x16, 32x32.

Upvotes: 3

Related Questions