Search code examples
javafxml

FXML: Alternate Uses


It is possible to use FXML to load non-GUI objects into memory? For example, I am creating a simple "voting" software for my school. All it needs is the list of "elective-posts" and the corresponding candidates along with other things like sets of "properties" of the posts and candidates.

What I want to do is, that I write the data in a FXML file and then load it using a FXMLLoader.


Solution

  • Yes, FXML can be used to create arbitrary objects. You'd define the objects just like you would any GUI object. You just have to make sure that:

    • You follow Java getter/setter naming conventions
    • If you have a setter named setField then in the FXML the attribute would be field="value"
    • Unless you are using JavaFX properties the binding syntax won't work
    • If you don't have a setter but you can set the field via a constructor (or you don't have a default constructor) then you have to annotate the constructor parameters with NamedArg

    Here's a small example.

    Animal.java

    package com.example;
    
    import javafx.beans.NamedArg;
    
    public class Animal {
    
        private final String name;
        private boolean housePet;
    
        public Animal(@NamedArg("name") String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        public boolean isHousePet() {
            return housePet;
        }
    
        public void setHousePet(boolean housePet) {
            this.housePet = housePet;
        }
    
        @Override
        public String toString() {
            return "Animal[name=" + name + ", housePet=" + housePet + "]";
        }
    
    }
    

    Main.java

    package com.example;
    
    import java.io.IOException;
    import java.util.List;
    import javafx.fxml.FXMLLoader;
    
    public class Main {
    
        public static void main(String[] args) throws IOException {
            List<Animal> list = FXMLLoader.load(Main.class.getResource("Main.fxml"));
            list.forEach(System.out::println);
        }
    
    }
    

    Main.fxml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import com.example.Animal?>
    <?import java.util.ArrayList?>
    
    <ArrayList xmlns="http://javafx.com/javafx/10.0.2" xmlns:fx="http://javafx.com/fxml/1">
    
        <Animal name="Cat" housePet="true"/>
        <Animal name="Dog" housePet="true"/>
        <Animal name="Bear" housePet="false"/>
        <Animal name="Wolf" housePet="false"/>
    
        <!-- Another way of declaring an Animal -->
    
        <Animal>
            <name>Snake</name>
            <housePet>true</housePet>
        </Animal>
    
    </ArrayList>
    

    Running Main prints the following:

    Animal[name=Cat, housePet=true]
    Animal[name=Dog, housePet=true]
    Animal[name=Bear, housePet=false]
    Animal[name=Wolf, housePet=false]
    Animal[name=Snake, housePet=true]