Search code examples
javafxstaticsceneinitializer

JavaFx- initializing scenes in a static way


I want to create a final class, having only static methods- an instance of this class will not be needed- it should be a static container. This class is supposed to have a map field containing created scenes. Now the problem is- method getClass() is not static and I cannot contain it in my static initializer block. Is there a way of creating scenes from FXML files without the use of non-static methods?

Here is the code:

package gui;

import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;

import java.util.Map;
import java.util.TreeMap;

public class ViewManager {

    /**
     * Class containing constant height and width of the window. 
     */
    public static final class Bounds{
        public static final int HEIGHT = 800;
        public static final int WIDTH = 800;
    }

    /**
     * Enum class containing paths to following scenes. 
     */
    public enum SceneName{
        LOGIN_VIEW("/login_view.fxml"),
        MAIN_VIEW("/main_view.fxml");

        private String path;

        SceneName(String path) {
            this.path = path;
        }

        @Override
        public String toString() {
            return path;
        }
    }

    private static Map<SceneName, Scene> sceneContainer;

    static{
        sceneContainer = new TreeMap<>();

        for(SceneName sceneName : SceneName.values()) {
            //here is the non-static reference
            Parent root = FXMLLoader.load(getClass().getResource(SceneName.LOGIN_VIEW.toString())); 
            sceneContainer.put(SceneName.LOGIN_VIEW, new Scene(root, Bounds.HEIGHT, Bounds.WIDTH));
        }
    }

    public static Map<SceneName, Scene> getSceneContainer() {
        return sceneContainer;
    }

}

Solution

  • If you only need access to a certain Class instance, simply use ClassName.class:

    // also changed this to use the loop variable instead of loading the same scene twice
    Parent root = FXMLLoader.load(ViewManager.class.getResource(sceneName.toString()));
    sceneContainer.put(sceneName, new Scene(root, Bounds.HEIGHT, Bounds.WIDTH));
    

    In general using static too often should be avoided though. A singleton could be the better option. Even better if you're able to pass a ViewManager instance to all the classes that need it... (Taking a look at dependency injection may be a good idea.)