JavaFX Tutorials

Tuesday, May 30, 2017

JavaFX Image Error Handling

ImageView is a JavaFX node that contains an Image.  When working with a classpath resource, an error is thrown immediately if an Image resource is not found.  However, you need to have the background flag set if your Image source is an absolute URL.

The following code will throw an exception if the resource is not on the classpath

        Image badImage = new Image("images/NOTFOUND.png");

A stack trace will look something like this

Caused by: java.lang.IllegalArgumentException: Invalid URL or resource not found
at javafx.scene.image.Image.validateUrl(Image.java:1110)
... 11 more

Similar code using an absolute URL will fail without throwing an error.  If using an ImageView, this results in either a blank area where the images should be shown or nothing, depending on the container.


For example,

       Image missingImage = new Image("https://www.bekwam.net/IMAGENOTFOUND.png", false);

Will not throw an Exception.

The Image class has several properties that are activated when the background loading flag is set.  These properties are
  1. progressProperty
  2. errorProperty
  3. exceptionProperty
To use these properties, either bind to them or add listeners.

progressProperty reports a double value of the percent complete of the Image load operation.  errorProperty is a boolean flag indicating that the background load operation failed.  exceptionProperty is set with errorProperty but contains the detailed.

Output from a progressProperty listener looks like

progress=0.20136880663196452
progress=0.30855986119144013
progress=0.4566223250433777
progress=0.6046847888953152
progress=0.7527472527472527
progress=0.9008097165991903
progress=1.0

Output from listeners on errorProperty and exceptionProperty looks like

exception=class java.util.concurrent.ExecutionException, 
msg=java.io.FileNotFoundException: https://www.bekwam.net/IMAGENOTFOUND.png
error=true

Unless you are writing sample code, it is best to use the background loading flag with Images to make sure that you're handling the not found or other error correctly.  Background loading is less important with Image code you ship yourself -- say in an /images folders in a JAR -- because you won't face an unreliable network, can test those images beforehand, and are already provided an IllegalArgumentException.  Large images may need it however.

Code

The demo program used in this article follows.

public class NotFoundHandlingApp extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {

        Image goodImage = new Image("https://www.bekwam.com/images/bekwam_logo_hdr_rounded.png", true);
        goodImage.progressProperty().addListener((obs,ov,nv) -> System.out.println("progress=" + nv));

        ImageView goodImageView = new ImageView(goodImage);

        Image missingImage = new Image("https://www.bekwam.net/IMAGENOTFOUND.png", true);

        // not called
        missingImage.errorProperty().addListener(
                (obs,ov,nv) -> System.out.println("error=" + nv)
        );

        // not called also
        missingImage.exceptionProperty().addListener(
                (obs,ov,nv) -> System.out.println("exception=" + nv.getClass() + ", msg=" + nv.getMessage())
        );

        ImageView missingImageView = new ImageView(missingImage);

        VBox vbox = new VBox(goodImageView, missingImageView);

        Scene scene = new Scene(vbox);

        primaryStage.setScene( scene );
        primaryStage.show();
    }

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


No comments:

Post a Comment