Sunday, September 20, 2015

Displaying images from files in JavaFX

As I continue to both employ JavaFX in my own code and teach JavaFX in my courses, I am slowly learning how to perform tasks I used to do in Swing in new ways.  The latest example is the all-important task of opening image files.

The strategy employed in this example is to set the image file as a background for a JavaFX Pane object.  Opening the image is a straightforward use of the JavaFX file chooser dialog.  Error handling is done via a simple error dialog created as an Alert.  Displaying the image requires the following steps:

  • Transform the File object into a URL, and use this to create an Image object.
  • Create a BackgroundSize for the object.  
    • By setting the height and width to AUTO, the image will automatically resize as the window displaying it is resized. 
    • It will not deform the image; if the aspect ratio of the displaying window does not match the image, the image will be truncated.
  • Create a BackgroundImage object.
    • The first parameter passes the Image object to use as its basis.
    • The second and third parameters control whether the object is repeated in the X and Y directions.  For this example, I deemed this undesirable.
    • The fourth parameter centers the image in the background.
    • The final parameter is the BackgroundSize object created before. 
  • Finally, we designate the BackgroundImage as the Pane's background.

import java.io.File;
import java.net.MalformedURLException;

import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundImage;
import javafx.scene.layout.BackgroundPosition;
import javafx.scene.layout.BackgroundRepeat;
import javafx.scene.layout.BackgroundSize;
import javafx.scene.layout.Pane;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;

public class DemoController {
 @FXML
 Pane pane;
 
 @FXML
 Button open;
 
 @FXML
 void initialize() {
  open.setOnAction(event -> imageOpener());
 }
 
 void imageOpener() {
  File imgFile = openImage();
  try {
   if (imgFile != null) {
    displayImage(imgFile);
   } 
  } catch (MalformedURLException e) {
   showError(e);
  }
 }
 
 File openImage() {
  FileChooser fileChooser = new FileChooser();
  fileChooser.setTitle("Select an Image File");
  fileChooser.getExtensionFilters().add(new ExtensionFilter(
    "Image Files", "*.png", "*.jpg", "*.gif"));
  return fileChooser.showOpenDialog(null);
 }
 
 void displayImage(File imgFile) throws MalformedURLException {
  Image background = new Image(imgFile.toURI().toURL().toString());
  BackgroundSize size = new BackgroundSize(BackgroundSize.AUTO,
    BackgroundSize.AUTO, false, false, true, true);
  BackgroundImage bimg = new BackgroundImage(background,
    BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT,
    BackgroundPosition.CENTER, size);
  pane.setBackground(new Background(bimg));
 }
 
 void showError(Exception e) {
  Alert info = new Alert(AlertType.ERROR);
  info.setTitle("Image not found");
  info.setHeaderText("Image not found");
  info.setContentText(e.getMessage());
  info.showAndWait();
 }
}

No comments:

Post a Comment