Javafx - Initialize components only when the scene is requested

Asked

Viewed 122 times

1

I’m trying to initialize some components, but I realized that the fxml controller initialize method is initialized before the scene is placed in Stage, this is the way I use to manage the scenes:

Scenemanager.java

package br.com.ivesti.ivarejo.util;

import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;

public class SceneManager {

    private static Stage mStage;

    private static Scene mSceneCadastrarUsuario, mSceneLogin, mSceneMainWindow;

    private static volatile SceneManager mInstance;

    private SceneManager(){
        initialize();
    }

    private void initialize(){
        try {

            if (mSceneCadastrarUsuario == null)
                mSceneCadastrarUsuario = new Scene(FXMLLoader.load(getClass().getResource("../ui/cadastrar_usuario_dialog.fxml")));


            if(mSceneLogin == null)
                mSceneLogin = new Scene(FXMLLoader.load(getClass().getResource("../ui/login_dialog.fxml")));

            if(mSceneMainWindow == null) {
                mSceneMainWindow = new Scene(FXMLLoader.load(getClass().getResource("../ui/dashboard_dialog.fxml")));
                mSceneMainWindow.getStylesheets().addAll(getClass().getResource("../css/style.css").toString());
            }

        }catch (IOException | NullPointerException e){
            System.err.println("Falha em obter a cena: " + e.getMessage());
            System.exit(-1);
        }
    }

    public void setStage(Stage stage){

        if(mStage == null){
            mStage = stage;
        }

    }

    public void changeScene(Scenes scenes){

        mStage.setResizable(false);

        switch (scenes){

            case CADASTRAR_USUARIO:
                mStage.setScene(mSceneCadastrarUsuario);
                break;

            case LOGIN:
                mStage.setScene(mSceneLogin);
                break;

            case MAIN_WINDOW:
                mStage.setResizable(true);
                mStage.setScene(mSceneMainWindow);
                break;

        }

    }

    public static SceneManager getManager(){

        if(mInstance == null){

            synchronized (SceneManager.class){

                if(mInstance == null)
                    mInstance = new SceneManager();

            }

        }

        return mInstance;
    }

    public enum Scenes{
        LOGIN, CADASTRAR_USUARIO, MAIN_WINDOW
    }

}

Dashboardcontroller.java

package br.com.ivesti.ivarejo.controllers;

import br.com.ivesti.ivarejo.util.Session;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.text.Text;

import java.net.URL;
import java.util.ResourceBundle;

public class DashboardController implements Initializable {

    /*    Componentes    */

    @FXML
    private Text tUsuarioAtual;

    /*    Eventos    */

    @FXML
    private void onUsuariosClicked(ActionEvent event){
        tUsuarioAtual.setText(Session.getSession().getString("u_name"));
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {

        tUsuarioAtual.setText(Session.getSession().getString("u_name"));

    }

}

So how to do to initialize be called only when SceneManager.getManager().changeScene(SceneManager.Scenes.MAIN_WINDOW); is called?

1 answer

0

I may be mistaken, but it wouldn’t simply create the variables and just arrow them at the time of using the FXMLLoader, would first remove this:

    try {

        if (mSceneCadastrarUsuario == null)
            mSceneCadastrarUsuario = new Scene(FXMLLoader.load(getClass().getResource("../ui/cadastrar_usuario_dialog.fxml")));


        if(mSceneLogin == null)
            mSceneLogin = new Scene(FXMLLoader.load(getClass().getResource("../ui/login_dialog.fxml")));

        if(mSceneMainWindow == null) {
            mSceneMainWindow = new Scene(FXMLLoader.load(getClass().getResource("../ui/dashboard_dialog.fxml")));
            mSceneMainWindow.getStylesheets().addAll(getClass().getResource("../css/style.css").toString());
        }

    }catch (IOException | NullPointerException e){
        System.err.println("Falha em obter a cena: " + e.getMessage());
        System.exit(-1);
    }

And I would call inside the switch itself so:

    switch (scenes){

        case CADASTRAR_USUARIO:
            if (mSceneCadastrarUsuario == null) {
                mSceneCadastrarUsuario = new Scene(FXMLLoader.load(getClass().getResource("../ui/cadastrar_usuario_dialog.fxml")));
            }

            mStage.setScene(mSceneCadastrarUsuario);
            break;

        case LOGIN:
            if(mSceneLogin == null) {
                mSceneLogin = new Scene(FXMLLoader.load(getClass().getResource("../ui/login_dialog.fxml")));
            }

            mStage.setScene(mSceneLogin);
            break;

        case MAIN_WINDOW:
            mStage.setResizable(true);

            if(mSceneMainWindow == null) {
                mSceneMainWindow = new Scene(FXMLLoader.load(getClass().getResource("../ui/dashboard_dialog.fxml")));
                mSceneMainWindow.getStylesheets().addAll(getClass().getResource("../css/style.css").toString());
            }

            mStage.setScene(mSceneMainWindow);
            break;

    }

You could even create an auxiliary method to load the classes and fxml and apply Try/catch inside it, although if there is an error loading this is because it was during the development that something was missing and should be corrected.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.