Images and BorderPanes in JavaFX and FXML 1


For this entry, I have decided to introduce 2 things at the same time:  working with images in your JavaFX/FXML application and using the BorderPane as a layout container for your application.  Using images is very easy in JavaFX/FXML – simply create an Image object that points to an image file (either stored locally or from a URL on the Internet), then use an ImageViewer to display the image.  Couldn’t be easier.  Now let’s talk briefly about the BorderPane container.


Learn to Code!


What is a BorderPane?

Like the GridPane and the FlowPane, the BorderPane is a container that you can use to arrange the layout of your application.  It comes with up to 5 distinct ‘zones’ or ‘regions’: top, bottom, center, left and right.  (Side note – in Swing these are still called by their geographic region names of north, center, south, east and west).  You can place anything you want in each region – either a single control or another container like an HBOX or VBOX if you want multiple controls such as buttons.  We will be doing both in this example.  As you can see here, the center region is the star of the show and it takes up most of the room in the BorderPane layout.  You don’t have to use all of the regions if you don’t need them – the sample little application we will be building only uses the top, center and bottom regions.

JavaFX BorderPane

borderpane

 JavaFX and Images, Featuring the BorderPane

Step 1 – Declare Objects Needed

We need 4 buttons and this thing called an ImageView that will display our image.  We also need an HBox to line up the buttons that will display our images.  The ‘Clear’ button will live by itself in the Bottom zone of the BorderPane.

public class ImageBorderPaneFX extends Application { 
    Button btnempire, btncentral, btnliberty, btnclear;
    ImageView imgpic;
    HBox btnbox;

Step 2 – Create Buttons and Attach to Code

If you have read any other examples on my site, this is pretty standard stuff.  We make each button and then tell it to go looking for a method called ‘handleButtonAction’ when it gets clicked on so it knows what to do.  (Side note – you can call this other method anything you want to, but I like to use the name ‘handleButtonAction’ – because in the FXML version this is name that will be used when it is created automatically by NetBeans.  This way I can just copy and paste this code into the FXML version later.  Very clever, yes?)

public void start(Stage primaryStage) {
    btnempire=new Button("Empire State Building");
    btncentral=new Button("Central Park");
    btnliberty=new Button("Statue of Liberty");
    btnclear=new Button("Clear");
 
    btnempire.setOnAction(e->handleButtonAction(e));
    btncentral.setOnAction(e->handleButtonAction(e));
    btnliberty.setOnAction(e->handleButtonAction(e));
    btnclear.setOnAction(e->handleButtonAction(e));

Step 3 – Create HBox Container and ImageView

The HBox contains the 3 image buttons, complete with spacing and padding to spread them out a little.  As for the ImageView, I can make it without passing anything in since I want it to be empty to start.  If you want an image to be shown right away you can send in an image file when you construct it too, as in:

Image img=new Image(“file:/src/images/pic.jpg”);
imgpic=new ImageView(img);

   //put top 3 buttons into a box
    btnbox=new HBox(btnempire, btnliberty,btncentral);
    btnbox.setSpacing(10);
    btnbox.setPadding(new Insets(20));
    //make the image
    imgpic=new ImageView();

Step 4 – Create the BorderPane

Here is where we feature the main code required for the BorderPane.  By default your application uses a StackPane so change it to a BorderPane (and add the required import as usual).  After setting the padding we simply place things into the regions by using ‘setTop’, ‘setBottom’, ‘setCenter’ and passing in whatever we want to be placed there.  I can also tell the BorderPane to place the bottom button in the middle of that region by using the .setAlignment method.

    //create the BorderPane
    BorderPane root = new BorderPane();
    root.setPadding(new Insets(10));

    //add components to regions of BorderPane 
    root.setTop(btnbox);
    root.setCenter(imgpic);
    root.setBottom(btnclear);
    //center the button in the bottom region
    BorderPane.setAlignment(btnclear,Pos.CENTER);

Step 5 – Rest of the Start Method

This is the usual code that comes with the JavaFX template.  I have adjusted the size of the application to 450 by 250 and set the title to ‘JavaFX – Images and Border Panes’

   Scene scene = new Scene(root, 450, 250);
 
   primaryStage.setTitle("JavaFX - Images and Border Panes");
   primaryStage.setScene(scene);
   primaryStage.show();
 }  //end of start method

Step 6 – Code for the Buttons

Whenever a button is clicked this code will kick in.  All we need to do is create an Image object and point it to the right file depending on which button was clicked (or null if the clear button was clicked).  Then we use the ‘setImage” method of the ImageView to display the chosen image.

Notice where the code goes looking for the image file.  Be default it will start at the root of your application so be careful where you place your images.  This is a really important step so I have included it after this step (see below).

private void handleButtonAction(ActionEvent event) {
 
   Image img;
   if(event.getSource()==btnempire) 
     img=new Image("file:src/images/empstate.jpeg");
   else if(event.getSource()==btnliberty) 
     img=new Image("file:src/images/statlib.jpeg");
   else if(event.getSource()==btncentral) 
     img=new Image("file:src/images/centpark.jpeg");
   else
     img=null;
   imgpic.setImage(img);
 }
 
 public static void main(String[] args) {
    launch(args);
 }
 
} //end of class

Step 7 – Place Images in Project

This isn’t a coding step yet it is just as important as the other steps.  If you do not place your images in the right place your application can’t find them and the whole thing wont work.  If you notice in Step 6, the code goes looking for images in a folder called ‘images’ which is placed inside the ‘src’ folder where the program is stored.  This is where you need to place the images.  You can use any images you want of course, but if you want to use mine go right ahead – I have put them here for that purpose.

Image Folder in JavaFX


centpark empstate statlib

FXML and Images, Featuring the BorderPane

Step 1 – Declare @FXML Variables

Like the JavaFX Version, we need to declare the same buttons and ImageView objects, but each on a separate line with @FXML above each one.

We do NOT need to declare the HBox since there is no code reference to it later so it can just be drawn in Scene Builder.

public class ImageBorderPane implements Initializable {    
    @FXML
    private Button btnempire;
    @FXML
    private Button btnliberty;
    @FXML
    private Button btncentral;
    @FXML
    private Button btnclear;
    @FXML
    private ImageView imgpic;

Step 2 – Complete the Button Code

Or more accurately, copy the code from the JavaFX version with the @FXML directive on top.  Since this method will be connected to each button in Scene Builder, the @FXML directive will allow it to be ‘seen’ in Scene Builder along with all the components.

The code is otherwise identical so there is no need to re-explain it (see step 6 in the JavaFX version for the explanation).  Like the other example, this version assumes you have an ‘images’ folder inside your ‘src’ folder and have placed your images in there.

@FXML
private void handleButtonAction(ActionEvent event) {
  Image img;
  if(event.getSource()==btnempire) 
    img=new Image("file:src/images/empstate.jpeg");
  else if(event.getSource()==btnliberty) 
    img=new Image("file:src/images/statlib.jpeg");
  else if(event.getSource()==btncentral) 
    img=new Image("file:src/images/centpark.jpeg");
  else
    img=null;
  imgpic.setImage(img);
}

 @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO
    }    
    
}//end class

Step 3 – Design the Application in Scene Builder

For this entry, I have decided just to include a video (with no audio) showing the steps I used to create the 450 by 250 screen in Scene Builder.  It is (or soon will be) also available with audio on my YouTube channel as a complete video where I also explain all the code and show BOTH methods to create this simple application.