JavaFX ImageView Example
1. Introduction
JavaFX exposes easy-to-use API for painting images on its stage via the javafx.scene.image.ImageView
class. An instance of ImageView
class does not merely renders images loaded instance of javafx.scene.image.Image
class, but also provides a variety of flexible manipulations to control various aspects of image rendering; in this post we are going to have a look at them. We would be using JavaFX API version 8 from JDK 8.
2. First Things First: Load the Image
Any image that has to be rendered on a JavaFX stage must be first loaded into memory. The in-memory representation of any image is, as mentioned earlier, is through an instance of the Image
class. There are a variety of easy ways for loading an image via the Image
class, however, there is a caveat: not all images can be represented in-memory via the Image
instance; only BMP, GIF, JPEG, PNG are valid formats as of now.
Following are two of the most frequently used mechanisms of loading an image via the Image class:
2.1 InputStream
The Image class has a variety of overloaded public constructors, one of them takes an InputStream
as an argument. And thus any InputStream
which represents a valid image can be passed to this constructor for loading that particular image. Following code snippet illustrates this idiom:
FileInputStream imageStream = new FileInputStream("/path/to/the/image"); Image image = new Image (imageStream );
Note that this constructor can potentially throw a NullPointerException
if the passed InputStream
is null; consequently, the calling method should take proper care of either handling this exception or re-throwing it further into the method call stack.
Nevertheless, once the constructor successfully executes, we would have the image loaded into memory for rendering onto the JavaFX stage.
2.2 url
The Image
class has another public single argument constructor which takes a String
url.
public Image(String url)
The very fact that we can directly pass an url gives us the flexibility not just to load image from a local file system but also to point to an image exposed on some network via its url; please follow the following code snippets for illustrations:
Image imageOnLocalFileSystem = new Image("/path/to/the/image/on/filesystem"); Image imageOnNetwork = new Image("http://www.imgion.com/images/01/Voilet-Flower-.jpg");
It is noteworthy that this constructor may throw NullPointerException
when the url is null; it may also throw IllegalArgumentException
when url is invalid or unsupported.
Note that ImageView
class also has a dedicated constructor which takes a String
url pointing to the image:
public ImageView(String url)
We would demonstrate this approach as well in the final demonstrative application but note that using this approach does not reduce the need of an Image
instance because the run time does create an Image
instance based on the url passed by us. What is achieved using this approach is that the burden of instantiating the Image class is deferred to the JavaFX run time. Internally this is what happens:
public ImageView(String url) { this(new Image(url)); }
This constructor also throws exceptions which must be handled by the callers.
3. Load ImageView with Image
Once an image is successfully loaded, all that is required is to initialize or set the ImageView.image
property which is of type ObjectProperty<Image>
and there are publicly exposed APIs for doing this, consider the following demonstrations:
3.1 Initialize ImageView.image
ImageView.image
can be initialized during ImageView
instance construction itself by passing relevant Image
instance. Consider the following ImageView
constructor:
public ImageView(Image image)
3.2 Set Image via relevant Setter method
If Image instance cannot be passed during ImageView
instance creation, ImageView.image
can still be set using the following method call on ImageView
instance:
public final void setImage(Image value)
4. Time to render Image
Once ImageView.image
has been successfully initialized, ImageView can be associated with the Scene graph. Note that ImageView
is-a javafx.scene.Node
and therefore, an ImageView
instance can be set as a “child” to a javafx.scene.layout.Pane
, let us say:
Image image = new Image(String url); ImageView imageView = new ImageView (image); HBox hbox = new HBox(); hbox.getChildren().add(imageView ); Scene scene = new Scene(hbox);
5. Other Flexibilities
The ImageView
class does not just render your image, but it also provides a whole lot of other functionalities for common use-cases. In the subsequent sub-sections we would go through them:
5.1 Image resizing with/without preserving the aspect ratio
ImageView
class has the following two methods which could be used to “fit” the image inside the given dimensions of width and height:
public final void setFitWidth(double value) public final void setFitHeight(double value)
However, note that changing any of these dimensions does not guarantee that the JavaFX runtime would honor the aspect ratio of the image! To maintain the aspect ratio while changing any or both of these dimensions, we must explicitly set the ImageView
attribute preserveRatio
as true
using the following method call:
public final void setPreserveRatio(boolean value)
5.2 Setting Viewport
ImageView
class also provides functionality to provide a “Viewport” into the image. We may understand viewport as a window through which we may be viewing the image and thus, the dimensions of the viewport would dictate the area of the original image visible. In other words, viewport would mask every other area of the image exposing only that area which corresponds to the position and dimensions of the viewport. The related APIs are as follows:
ObjectProperty<Rectangle2D> viewport public final void setViewport(Rectangle2D value)
Following is the code snippet which uses the above API:
Rectangle2D viewPort = new Rectangle2D(10, 20, 50, 60); ImageView imageView = new ImageView (someImage); imageView.setViewport(viewPort);
Effectively what this means is that we would be creating a viewport window beginning at coordinate (10, 20) and of dimensions 50×60 on the image for its visibility.
5.3 ImageView Transformations
Remember in section 4 we mentioned that ImageView
is-a Node
, and therefore ImageView
inherits all the members from the Node
class including the transformation functions. This means that the before final rendering, the image could be transformed as per application requirements. Following is one example of such a transformation:
ImageView imageView = new ImageView (someImage); imageView.setRotate(50);
The above code snippet would rotate someImage
50 degrees clockwise.
6. Bringing All Bits Together
We have discussed quite a few APIs from the Image
and ImageView
class, now it is time to bring all of them together in a demonstrative application:
ImageViewExample.java
package imageviewexample; import javafx.application.Application; import javafx.geometry.Rectangle2D; import javafx.scene.Scene; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.HBox; import javafx.stage.Stage; /** * * @author NawazishMohammad * ImageViewExample demonstrates the various ways of loading an image * and rendering the same on the JavaFX stage.It also demonstrates the * various functionalities that ImageView class has to offer for image rendering. */ public class ImageViewExample extends Application { @Override public void start(Stage primaryStage) { /** * In the following example image is assumed to be present * in a directory on the application class path */ Image image = new Image("imageresource/Yellow-Vector-Flower-.jpg"); /** * imageView1 takes image and manipulates it size, * and preserves its aspect ratio */ ImageView imageView1 = new ImageView(image); imageView1.setFitHeight(100); imageView1.setPreserveRatio(true); /** * imageView2 manipulates the width of the image, * preserves the aspect ratio and rotates the image by 90 degrees */ ImageView imageView2 = new ImageView(image); imageView2.setFitWidth(200); imageView2.setPreserveRatio(true); imageView2.setRotate(90); /** * We set a viewport on imageView3 creating an illusion of zoom-in effect */ Rectangle2D viewPort = new Rectangle2D(925, 50, 600, 600); ImageView imageView3 = new ImageView(image); imageView3.setFitWidth(100); imageView3.setPreserveRatio(true); imageView3.setViewport(viewPort); /** * imageView4 receives its image from a public url */ String flowerImageStr = "http://www.imgion.com/images/01/Voilet-Flower-.jpg"; Image flowerImage = new Image(flowerImageStr); ImageView imageView4 = new ImageView(flowerImage); imageView4.setFitWidth(200); imageView4.setPreserveRatio(true); /** * imageView5 demonstrates setting ImageView.image using the JavaFX's Property API */ ImageView imageView5 = new ImageView(); imageView5.imageProperty().set(image); imageView5.setFitWidth(200); imageView5.setPreserveRatio(true); imageView5.setRotate(-90); /** * imageView6 directly points to the url of the image- * obviating the need for an Image class instantiation */ String imgUrl = "http://www.imgion.com/images/01/Voilet-Flower-.jpg"; ImageView imageView6 = new ImageView(imgUrl); imageView6.setFitWidth(200); imageView6.setFitHeight(200); imageView6.setPreserveRatio(true); HBox hbox = new HBox(10); hbox.getChildren().addAll(imageView1,imageView2, imageView3,imageView4, imageView5,imageView6); Scene scene = new Scene(hbox); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } }
7. Conclusion
JavaFX’s Image and ImageView classes provide an easy to use API for rendering images on JavaFX stage. It is as easy as pointing to your image via the Image instance and then handing it over the ImageView instance for painting. Besides plain-vanilla painting, ImageView also offers you to transform the images as per requirements.
8. Download The Eclipse Project
This was an example about rendering images on JavaFX stage using ImageView and Image APIs.
You can download the entire Eclipse project here: ImageViewExample