IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaFX Discussion :

Erreur lors de l'accès à une méthode


Sujet :

JavaFX

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2014
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2014
    Messages : 12
    Points : 5
    Points
    5
    Par défaut Erreur lors de l'accès à une méthode
    Bonjour à tous,

    Le titre est un peu barbare mais je vais tenter d'expliquer au mieux mon souci, je précise que j'ai commencé à utiliser l'API JavaFX il y a très peu de temps, j'ai par conséquent pas mal de chose que j'ai du mal à assimiler mais j'ai soif d'apprendre

    Alors en gros mon problème :

    J'ai un programme qui comporte plusieurs scène (un petit jeux que je développe avec deux amis), il se trouve, que sur l'une de ces scènes il y a un plateau de jeux qui comporte des cases, ces dernières sont des Objets instancié d'une classe Case extends Pane avec des paramètres qui sont récupéré dans une bdd.
    Jusque là tout va bien.
    Lorsque j'instancie mes objets susdités dans l'Initializer, au lancement du programme, tout se passe parfaitement bien.

    La déclaration dans l'Initializer :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
     
    	private Pane[] case_Echiquier = new Case [64];
     
    	@FXML
    	private GridPane IdGP;
     
    	private ResultSet rs;
     
    	private int gridX = 0;
    	private int gridY = 0;
     
            public void initialize(URL location, ResourceBundle resources) {
                    rs = Arsghuul.c.requete("SELECT * from CASEP");
    		try {
    			while(rs.next()){
    				int caseNum = rs.getInt(1);
    				int casePiegeId = rs.getInt(2);
    				boolean caseEtatPiege = rs.getBoolean(3);
    				int casePlateauId = rs.getInt(4);
    				int casePionId = rs.getInt(5);
    				int row = rs.getRow();
    				case_Echiquier[row-1] = new Case(caseNum, casePiegeId, caseEtatPiege, casePlateauId, casePionId);
    				case_Echiquier[row-1].setPrefSize(200, 200);
    				try{
    					IdGP.add(case_Echiquier[row-1], gridX, gridY);
     
    					if (gridX == 7){
    						gridX = 0;
    						gridY++;
    					}else{
    						gridX++;
    					}
    					System.out.println("La case "+row+" a bien été ajouté.");
    				}catch(Exception e ){
    					System.out.println("L'insertion de la case "+row+" a échoué.");
    					e.printStackTrace();
    				}
     
    				case_Echiquier[row-1].addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>(){
    					public void handle(MouseEvent e){
    						Case affiche = (Case) e.getSource();
    						System.out.println(affiche.getCaseNum());
    					}
    				});
     
    			}
    		} catch (SQLException e) {
    			e.printStackTrace();
    		}
           }
    Bon et mon problème alors ?
    Et bien c'est simple, c'est pas ce que je veux
    Je souhaite que lorsque l'on clique sur le bouton "lancer" de la page d'accueil du programme, l’exécution de ce code se fasse.
    Pour se faire, j'ai décidé de le mettre dans une méthode nommé "initCase()" que j'appelle grâce à un ActionEvent sur le dit bouton.

    L'ActionEvent du bouton lancer :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    	@FXML
    	public void clickBtnLancer(ActionEvent e){
    		if(typePartie == 1){
    			PlateauController.initCase();
    			myController.setScreen(Arsghuul.PlateauID);
    		}else{
    			myController.setScreen(Arsghuul.ArmeePersoID);
    		}
    	}
    La méthode initCase() :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
     
    	private static Pane[] case_Echiquier = new Case [64];
     
    	@FXML
    	private static GridPane IdGP;
     
    	private static ResultSet rs;
     
    	private static int gridX = 0;
    	private static int gridY = 0;
     
    	public static void initCase(){
    		rs = Arsghuul.c.requete("SELECT * from CASEP");
    		try {
    			while(rs.next()){
    				int caseNum = rs.getInt(1);
    				int casePiegeId = rs.getInt(2);
    				boolean caseEtatPiege = rs.getBoolean(3);
    				int casePlateauId = rs.getInt(4);
    				int casePionId = rs.getInt(5);
    				int row = rs.getRow();
    				case_Echiquier[row-1] = new Case(caseNum, casePiegeId, caseEtatPiege, casePlateauId, casePionId);
    				case_Echiquier[row-1].setPrefSize(200, 200);
    				try{
    					IdGP.add(case_Echiquier[row-1], gridX, gridY);
     
    					if (gridX == 7){
    						gridX = 0;
    						gridY++;
    					}else{
    						gridX++;
    					}
    					System.out.println("La case "+row+" a bien été ajouté.");
    				}catch(Exception e ){
    					System.out.println("L'insertion de la case "+row+" a échoué.");
    					e.printStackTrace();
    				}
     
    				case_Echiquier[row-1].addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>(){
    					public void handle(MouseEvent e){
    						Case affiche = (Case) e.getSource();
    						System.out.println(affiche.getCaseNum());
    					}
    				});
     
    			}
    		} catch (SQLException e) {
    			e.printStackTrace();
    		}
    	}
    Et l'erreur qui me fait devenir chauve :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    java.lang.NullPointerException at arsghuul.PlateauController.initCase(PlateauController.java:72)
    La ligne 72

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    IdGP.add(case_Echiquier[row-1], gridX, gridY);
    L'erreur pointe toujours vers mon GridPane, je ne comprend pas pourquoi ...
    C'est là que j'ai besoin de vous.
    Il ne me semble pas logique de pas pouvoir accéder aux coordonnées d'un GridPane après la construction de la page, au contraire même, ça voudrait dire qu'on peut plus la modifier ou accéder à son contenu quand la page est chargé ?
    Je vous cache pas que je suis perdu et ne sais plus trop vers où tourner ma réflexion ...

    Merci d'avance, j'espère que vous m'aiderez à sauver mes cheveux

    Pouette

  2. #2
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 856
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 856
    Points : 22 888
    Points
    22 888
    Billets dans le blog
    51
    Par défaut
    Y a un ou deux trucs que j'ai du mal à piger... initCase() semble être une méthode statique de la classe PlateauController mais IdGP est un membre d'instance (au fait, la convention c'est d'écrire les noms de variable avec la 1ere lettre en minuscule) qui est donc initialisé lorsque le FXML est chargé... donc c'est dans ton architecture qu'il y a un truc qui déralle...

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2014
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2014
    Messages : 12
    Points : 5
    Points
    5
    Par défaut
    Bonjour Bouye,

    Je travail sur le projet avec deux amis et j'avoue que ce manque de rigueur sur la normalisation de la déclaration de variable n'est pas de mon fait mais je manquerais pas de lui taper sur les doigts (il adore ça en plus :p).

    Ceci étant dit, j'avoue que tu me perd un peu.
    idGP est effectivement une variable d'instance, c'est une grille qui me sert à positionner les cases du jeu (comme un échiquier). L'objet que j'instancie est une scène.
    A la base, je ne souhaite pas que la méthode initCase() soit static mais Eclipse me l'impose et refuse de compiler dans le cas contraire.

    Mais j'ai quand même essayé de retirer le static pour voir mais il refuse de compiler (je ne peux pas faire appelle à une méthode non static depuis une classe static... et je n'ai que le main qui est encore static :s).

    Je suis perdu ...
    Si tu veux que je te montre d'autre partie du code, tout ce que tu voudra

  4. #4
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 856
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 856
    Points : 22 888
    Points
    22 888
    Billets dans le blog
    51
    Par défaut
    Dans le 1er premier bloc de code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    @FXML
    	private GridPane IdGP;
    Cette variable est marquée de l'annotation @FXML : elle est injectée par le FXMLoader dans le controleur lorsque le fichier FXML est chargé. Si c'est null c'est que :
    • Soit elle est mal déclarée dans le contrôleur (pas le même nom que le fx:id que dans le FXML).
    • soit tu initialises ton contrôleur n'importe comment. A moins que tu n'injectes ton contrôleur (ce que je n'ai jamais testé même si en théorie ça reste faisable) manuellement c'est le loader qui crée le controleur automatiquement en chargeant le FXML.


    Dans le dernier bloc de code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    @FXML
    	private static GridPane IdGP;
    On a une nouvelle variable avec le même nom que la 1ere mais statique... c'est un peu n'importe quoi.
    Elle est marquée @FXML .... Beuh c'est impossible, on ne peut initialiser que des variables d'instance via un FXMLoader, donc elle est nulle donc c'est normal, CQFD...

  5. #5
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2014
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2014
    Messages : 12
    Points : 5
    Points
    5
    Par défaut
    Cette histoire de static sur cette variable tombe sous le sens effectivement.
    Merci pour cette petite explication.

    Du coup j'ai viré le static pour me remémorer un peu l'erreur que j'avais.

    Lorsque je fais appelle à ma méthode (sur le bouton lancer je rapelle), j'ai un premier avertissement d'éclipse :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Cannot make a static reference to the non-static method initCase() from the type PlateauController
    C'est ce qui m'avais pousser à tout passer en static, mais c'est vrai qu'avec tes explication c'est pas logique.

    Bref, je suis fou et j'exécute tout de même mon code et cette fois c'est un beau :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    De ce que j'ai compris pour l'instant de l'API et des potentiel fois ou j'ai vue cette erreur, c'est quand on fait appelle à un élément qui n'existe pas...
    Mais mes éléments existe bien puisque si j'exécute le contenu de la méthode initCase() dans l'Initializer ça fonctionne.

    Peut être que ce qui me permet de changer de scène n'est pas adapté ?

    J'aimerais mettre l'intégralité de mon code mes il commence à être un peu long et je voudrais pas endormir les lecteurs avant la fin ^^.

    Mais grosso modo, je déclare toute mes scène dans mon main :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
     
    public class Arsghuul extends Application {
     
    	public static String AccueilID = new String ("Accueil");
    	public static String AccueilFile = new String ("Accueil.fxml");
    	public static String PlateauID = new String ("Plateau");
    	public static String PlateauFile = new String ("Plateau.fxml");
    	public static String ArmeePersoID = new String ("Armée Perso");
    	public static String ArmeePersoFile = new String ("ArmeePerso.fxml");
    	public static ConnectDB c;
     
    	@Override
    	 public void start(Stage primaryStage) {
     
    		try {
    			Arsghuul.c = new ConnectDB();
    			System.out.println("Connection établit");
    		} catch (SQLException e) {
    			System.out.println("Connection impossible !!!");
    		}
     
    		 ScreensController mainContainer = new ScreensController();
    		 mainContainer.loadScreen(Arsghuul.AccueilID, Arsghuul.AccueilFile);
    		 mainContainer.loadScreen(Arsghuul.PlateauID, Arsghuul.PlateauFile);
    		 mainContainer.loadScreen(Arsghuul.ArmeePersoID, Arsghuul.ArmeePersoFile);
     
    		 mainContainer.setScreen(Arsghuul.AccueilID);
     
    		 Group root = new Group();
    		 root.getChildren().addAll(mainContainer);
    		 Scene scene = new Scene(root, 1280, 800);
    		 primaryStage.setScene(scene);
    		 primaryStage.setResizable(false);
    		 primaryStage.show();
     
     
    	 }
     
    	public static void main(String[] args) {
    		launch(args);
    	}
     
    }
    Au début de chaque scène j'ai :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    	ScreensController myController;
     
    	public void setScreenParent(ScreensController screenPage) {
    		myController =  screenPage;
    	}
    et du coup un ScreenController qui s'occupe de charger la scène demandé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
     
    public class ScreensController extends StackPane{
     
    	private HashMap<String, Node> screens = new HashMap<String, Node>();
     
     
    	public ScreensController(){
    		super();
    	}
     
    	public void addScreen(String name, Node screen){
    		screens.put(name, screen);
    	}
     
    	public Node getScreen(String name){
    		return screens.get(name);
    	}
     
    	public boolean loadScreen(String name, String resource){
    		try{
    			FXMLLoader myLoader = new FXMLLoader(getClass().getResource(resource));
    			Parent loadScreen = (Parent) myLoader.load();
    			ControlledScreen myScreenController = ((ControlledScreen) myLoader.getController());
    			myScreenController.setScreenParent(this);
    			addScreen(name, loadScreen);
    			return true;
    		} catch (Exception e){
    			System.out.println(e.getMessage());
    			return false;
    		}
    	}
     
    	public boolean setScreen(final String name){
     
    		if (screens.get(name) != null){ //screen loaded
    			final DoubleProperty opacity = opacityProperty();
     
    			if(!getChildren().isEmpty()){ // s'il y a plus d'un screen				
    				Timeline fade = new Timeline(
    						new KeyFrame(Duration.ZERO, new KeyValue(opacity,1.0)),
    						new KeyFrame(new Duration(500), new EventHandler<ActionEvent>(){
    					//@Override
    					public void handle(ActionEvent t){
    							getChildren().remove(0);
    							getChildren().add(0, screens.get(name));
    							Timeline fadeIn = new Timeline(
    									new KeyFrame(Duration.ZERO, new KeyValue(opacity, 0.0)),
    									new KeyFrame(new Duration(600), new KeyValue(opacity, 1.0)));
    							fadeIn.play();
    					}
    			}, new KeyValue(opacity, 0.0)));
    			fade.play();
    		}else {
    				getChildren().add(screens.get(name));
    			}
    			return true;
    		} else {
    			System.out.println("La scène n'a pas été chargée !! \n"+name);
    			return false;
    		}
    	}
     
    	public boolean unloadScreen(String name){
    		if (screens.remove(name)==null){
    			System.out.println("la scène n'éxiste pas");
    			return false;
    		}
    		else {
    			return true;
    		}
    	}
     
    }
    J'ai rien inventer, j'ai suivis un tuto de Angela Caicedo sur le site d'oracle.
    J'ai essayé de le comprendre du mieux que j'ai pue et surtout de l'adapter à mes besoins mais j'ai surement zappé un truc.

  6. #6
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 856
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 856
    Points : 22 888
    Points
    22 888
    Billets dans le blog
    51
    Par défaut
    Bon, j'ai récupéré le dernier code poste et j'ai commenté la partie concernant la connexion BD. J'ai crée une classe vide ControlledScreen histoire que ça puisse compiler et j'ai lancé. Évidement ça ne va pas bien loin au-delà puisque je n'ai pas les FXML en question. Est-ce qu'il y a moyen d'avoir au moins le squelette des endroits qui posent problème ?

    Une petite suggestion très optionnelle : le préchargement des screens peut se faire dans la méthode init() de l'Application. Cette méthode n'est pas appelée sur le JavaFX Application Thread* donc il faudra être vigilant pour voir si une exception est levée. Mais l’intérêt de mettre le chargement (et la connection a la BD aussi d'ailleurs) la c'est surtout qu'alors il est possible d'utiliser un preloader (ex: splashscreen avec barre de chargement). En général le preloader est caché avant que la méthode start() ne soit appelée (start() est invoquée sur le JavaFX Application Thread*).

    On aurait alors un truc du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
        @Override
        public void init() throws Exception {
    	try {
    		Arsghuul.c = new ConnectDB();
    		System.out.println("Connection établit");
    	} catch (SQLException e) {
    		System.out.println("Connection impossible !!!");
    	}
            mainContainer = new ScreensController();
            mainContainer.loadScreen(Arsghuul.AccueilID, Arsghuul.AccueilFile);
            mainContainer.loadScreen(Arsghuul.PlateauID, Arsghuul.PlateauFile);
            mainContainer.loadScreen(Arsghuul.ArmeePersoID, Arsghuul.ArmeePersoFile);
        }
     
        @Override
        public void start(Stage primaryStage) {
            mainContainer.setScreen(Arsghuul.AccueilID);
     
            Group root = new Group();
            root.getChildren().addAll(mainContainer);
            Scene scene = new Scene(root, 1280, 800);
            primaryStage.setScene(scene);
            primaryStage.setResizable(false);
            primaryStage.show();
     
        }
    Pour moi ca passe mais uniquement car je n'ai pas les FXML (donc ce n'est pas un vrai test - bien qu'en théorie les contrôles peuvent être créés hors du JavaFX Application Thread*, dans la version actuelle, certains bugs font que tous le le peuvent pas ex: tous les tooltip et controles avec des menu popups - cela devrai etre corriger pour FX8_40 ou FX9). Évidement si une exception est levée, il faudra garder la manière de faire actuelle avec tout dans start().

    * Les objets Scene et Window doivent etre manipules sur le JavaFX Application Thread. De meme que tout composant rattache a une scène.

  7. #7
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2014
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2014
    Messages : 12
    Points : 5
    Points
    5
    Par défaut
    Bonsoir Bouye,

    J'y aurais passé quelques heures mais ça y est, j'ai trouvé la solution à ce problème ... Mes cheveux vont pouvoir se reposer.

    Je vais tenter d'expliquer au mieux la solution que j'ai trouvé.

    Tout es partie de cet histoire de static qui te chagriné tout autant que moi, j'ai fais de plus ample recherche sur notre ami Google sur une façon d'accéder à une méthode non-static depuis une méthode considéré static et j'ai eu un retour qui m'a semblait compliquer à assimiler dans mon petit crâne :

    - On ne peut accéder à ce genre de méthode qu'avec une instance de la class créé directement dans la class de départ... (ceci est une traduction approximative :p)

    Je sais pas si c'est bien claire, mais j'avoue que j'ai mis du temps à adapter ça à mon cas.

    Pour résumer, voilà comment j'ai réglé ça :

    - étape 1 : déterminer le moment ou mes pages sont chargé et comment l'instancier.

    C'est la partie qui m'a le plus torturé, mais à un moment, en relisant encore et encore mon code j'ai tiqué dans mon main :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    		 ScreensController mainContainer = new ScreensController();
    		 mainContainer.loadScreen(AccueilID, AccueilFile);
    		 mainContainer.loadScreen(PlateauID, PlateauFile);
    		 mainContainer.loadScreen(ArmeePersoID, ArmeePersoFile);
    Mais c'est bien sur, je fais appelle à la méthode loadScreen de ma classe ScreensController.

    petit rapelle :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    	public boolean loadScreen(String name, String resource){
    		try{
    			FXMLLoader myLoader = new FXMLLoader(getClass().getResource(resource));
    			Parent loadScreen = (Parent) myLoader.load();
    			ControlledScreen myScreenController = ((ControlledScreen) myLoader.getController());
    			myScreenController.setScreenParent(this);
    			addScreen(name, loadScreen);
    			return true;
    		} catch (Exception e){
    			System.out.println(e.getMessage());
    			return false;
    		}
    	}
    Maintenant, ça me paraît une évidence mais j'ai cogité un moment, toutes mes scènes se charge par ce loader au lancement du programme, c'est donc là qu'il faut que j'agisse et instancie mes scènes pour pouvoir accéder à leurs méthodes.
    Pour rappelle, mon problème était de pouvoir accéder à une méthode initCase() quand je chargeais la scène.

    Voilà le code après la petite modif :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
            private PlateauController test;
     
    	public boolean loadScreen(String name, String resource){
    		try{
    			FXMLLoader myLoader = new FXMLLoader(getClass().getResource(resource));
    			Parent loadScreen = (Parent) myLoader.load();
    			ControlledScreen myScreenController = ((ControlledScreen) myLoader.getController());
    			myScreenController.setScreenParent(this);
    			addScreen(name, loadScreen);
     
    			if (name.equals("Plateau")){
    				try {
    					test = (PlateauController)myLoader.getController();
    				} catch (Exception e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
    			return true;
    		} catch (Exception e){
    			System.out.println(e.getMessage());
    			return false;
    		}
    	}
    Etape 2 : Il faut maintenant que j'accède à la fameuse méthode de plateauController.

    C'est la partie simple, maintenant que j'ai instancié ma scène, dans mon ScreenController, j'accède à toute les méthodes de mon plateauController d'une simple ligne.
    Oui mais quand ?
    Et bien le chargement d'une scène est géré par ce fameux ScreenController et sa méthode setScreens().
    Donc, si le nom de la scène correspond à "Plateau", j’exécute ma méthode :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    	public boolean setScreen(final String name){
    		
    		if (screens.get(name) != null){ //screen loaded
    			final DoubleProperty opacity = opacityProperty();
    			
    			if(!getChildren().isEmpty()){ // s'il y a plus d'un screen				
    			        getChildren().remove(0);
    				getChildren().add(0, screens.get(name));
    			
                            if (name.equals("Plateau")){
    				try {
    					System.out.println(test);
    					test.initCase();
    				} catch (Exception e) {
    					e.printStackTrace();
    				}
    			}
    		}else {
    				getChildren().add(screens.get(name));
    			}
    			return true;
    		} else {
    			System.out.println("La scène n'a pas été chargée !! \n"+name);
    			return false;
    		}
    	}
    Voilà, j'espère que mes explication ont été claire, et peut être même intéressent pour certain, en tout cas ça fonctionne parfaitement sans que ça me paraisse trop bancale .

    Bouye, ça me plairait bien d'avoir ton avis sur cette façon de faire, en tout cas merci beaucoup pour le temps que tu as passé à m'aider.

    Bisous,

    Pouette

  8. #8
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 856
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 856
    Points : 22 888
    Points
    22 888
    Billets dans le blog
    51
    Par défaut
    Déjà, regarde aussi ce que j'ai poste un peu plus haut concernant le chargement des ressources (j'ai modifie mon post pendant que tu répondais). Ce que je propose n'est peut-etre pas faisable cependant a cause de bugs actuels dans l'API.

    Je ferai ça un peu différemment dans la mesure ou tu sera vraisemblablement amené a manipuler les contrôleurs d'autres écrans :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    private HashMap<String, Pair<Node, ControlledScreen >> screens = new HashMap<>();
     
     
    [...]
     
    FXMLLoader myLoader = new FXMLLoader(getClass().getResource(resource));
    Parent loadScreen = (Parent) myLoader.load();
    ControlledScreen myScreenController = ((ControlledScreen) myLoader.getController());
    myScreenController.setScreenParent(this);
    addScreen(name, loadScreen, myScreenController );
     
    [...]
     
    public void addScreen(String name, Node screen, ControlledScreen  screenController){
        screens.put(name, new Pair<>(screen, screenController));
    }
     
    public Node getScreen(String name) {
       return screens.get(name).getKey();
    }
     
    public ControlledScreen getScreenController(String name) {
       return screens.get(name).getValue();
    }
    Ca te permettrait de récupérer tes contrôleurs pour chacun de tes ecrans et aussi dans le cas du plateau d'appeler initCase() a un moment plus opportun (quel besoin d'initialiser les cases au chargement de l'app avant que le joueur ai lance son jeu ????)

  9. #9
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2014
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2014
    Messages : 12
    Points : 5
    Points
    5
    Par défaut
    Effectivement, je n'avais pas vue que tu avais édité ton message, désolé.

    Ce que tu me décrit dans ton précédant post est très intéressant, mais à partir de quand doit-on juger bon d'utiliser un preloader ?
    Dans mon cas je t'avoue que je ne vais pas excéder les 4 ou 5 scènes, le lancement de mon programme est casi instantané sur mon ordinateur, est-ce vraiment utile ?

    Par contre, ton dernier post, je ne comprend pas vraiment ce que tu veux dire.
    J'ai due mal expliqué le résultat que je recherchais. Ce que je voulais c'est justement ne pas avoir l'initialisation de mes cases au chargement de mon programme.

    Le dernier code que j'ai présenté m'a permis de palier à ça puisque la methode setScreen() n'est appelé qu'au changement de scène une fois le programme lancé contrairement à la méthode loadScreen() qui elle est appelé au lancement du programme.
    Récupérer l'instance de ma scène dans le loadScreen(), me permet d'accéder aux méthodes qui m’intéresse au moment où l'utilisateur accède à la scène en question.

    C'était très important d’aboutir à ce résultat pour pouvoir faire plusieurs partie de suite par exemple.

    Je suis encore un bébé du java, j'ai un peu peur de ne pas bien comprendre certaine chose parfois

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 14/02/2010, 19h14
  2. [IO] message d'erreur lors de l'acces à une image
    Par etoileDesNeiges dans le forum Entrée/Sortie
    Réponses: 5
    Dernier message: 24/05/2007, 13h31
  3. [TestStand] Erreur lors d'un accès à une Base de données
    Par capblans dans le forum Autres langages
    Réponses: 1
    Dernier message: 20/07/2005, 10h29
  4. Pb lors de l'accès à une surface DirectDraw
    Par Mark53 dans le forum DirectX
    Réponses: 8
    Dernier message: 30/11/2004, 00h03
  5. Erreur lors de modification d'une table
    Par seb.49 dans le forum SQL
    Réponses: 11
    Dernier message: 13/01/2003, 17h16

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo