Search code examples
imageurljavafxfxml

FXML Variable Tagging for Image URLs


I am working on a project where I need to switch between multiple images from a specific directory to use as a background for my program. Unfortunately, I can't hard code all of image paths into fxml as urls and switch between each one using fxids because I have too many images, and new images get added throughout the week. I created one fxid which is linked to a specific variable that holds the path to the image. This variable is a url which has the path "@../images/Planets/image1.png". fxml loads the button elements properly but fails to load the linked url associated with the given variable. I took the exact url and placed it directly into fxml which displayed the one image properly. I need help getting the url variable to be properly recognized in fxml. Below is my fxml code.

<AnchorPane fx:id="AP" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="main.java.controllers.PlanetController">
   <children>
      <fx:define>
      <URL fx:id="image"/>
      </fx:define>
      <ImageView fitHeight="721.0" fitWidth="1289.0">
         <image>
            <Image url="$image"/>
         </image>
      </ImageView>
      <Button fx:id="map" layoutX="709.0" layoutY="685.0" mnemonicParsing="false" onAction="#handleNext" text="Map" />
      <Button layoutX="428.0" layoutY="690.0" mnemonicParsing="false" text="Market" />
   </children>
</AnchorPane>

Here is the javafx code which loads the fxml document. Disregard the rootController. It sets a scene to a vBox.

@FXML
private URL image;

@FXML
public void handleTravelToRegion() {
image = new URL("@../images/Planets/image4.jpg");
try {
            URL url = this.getClass().getResource(getScene("destinationPlanet"));
            FXMLLoader loader = new FXMLLoader(url);
            Node scene = loader.load();
            rootController.setScene(scene);
        } catch (IOException e) {
            e.printStackTrace();
        }
}

Please help me get the <Image url="$image"/> to load the image variable. Your help will be greatly appreciated.


Solution

  • In case anyone else was having difficulties getting nodes setup as variables in their fxml document, please go to your initialize method in your controller class and add your desired node to your pane linked in your fxml document. In my case, I was using an anchorPane in my fxml document which I linked to my controller class using the @FXML tag. I needed to add an ImageView node containing a random image file to my anchor pane. All I needed to do was add the node inside the FXML initialize method, otherwise, no changes to my scene would be displayed. Below is the final outcome of my fxml document and controller class:

    <?xml version="1.0" encoding="UTF-8"?>
    <?import javafx.scene.layout.AnchorPane?>
    
    <AnchorPane fx:id="ap" maxHeight="-Infinity" maxWidth="-Infinity"
            minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="main.java.controllers.PlanetController">
    

    In my controller class, I needed to do the following:

    public class PlanetController implements Initializable {
    private ImageView background = new ImageView();
    
    @FXML
    private AnchorPane ap = new AnchorPane();
    
    public void initialize(URL url, ResourceBundle resourceBundle) {
        Random rand = new Random();
        File[] imageArray = new File("@../images/Planets/").listFiles();
        Image image = new Image(imageArray[rand.nextInt(imageArray.length)]
            .toURI().toString());
        background = new ImageView(image);
        ap.getChildren().add(background);
    }
    

    That was all I had to do to get the backgrounds to work.