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 :

Modifier les élèments d'un groupe


Sujet :

JavaFX

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2022
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 20
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2022
    Messages : 11
    Points : 9
    Points
    9
    Par défaut Modifier les élèments d'un groupe
    Bonsoir,

    Me voilà bloqué depuis quelques jours sur un problème, j'ai un projet de Memory, j'utilise donc JavaFX avec Scene Builder pour avoir une interface graphique, cependant je rencontre un problème. Je m'explique, lorsque que j'initie une partie, je créé donc une fenêtre contenant 20 groupes (eux-mêmes contenant 11 cartes), j'ai de plus un système de difficulté. J'ai donc une procédure (setupDiff1()) qui, lorsque je choisis une difficulté (en l'occurrence "facile"), désactive certains groupes et cartes (pour n'en laissé que 8 par exemple), cependant peu importe que j'essaie de modifier les propriétés de visibilité des cartes ou du groupe (avec SetVisible(Boolean) par exemple) ou que je change les déclarations @FXML private en public rien ne change, je suis bloqué et j'aimerais savoir si possible d'où vient le problème et s'il y a moyen de le régler ? Merci d'avance.

    Je vous mets le lien du gitHub avec mon projet si jamais : https://github.com/FlamySpeeddraw/Memory.

  2. #2
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Août 2005
    Messages : 6 840
    Points : 22 854
    Points
    22 854
    Billets dans le blog
    51
    Par défaut
    Quelques petites remarques ici et la, pas critiques pour ton soucis :
    • C'est GitHub. Pourquoi stocker un fichier ZIP (même pas protégé par un mot de passe) plutôt que de tout simplement charger du code ?
    • Tu es sur quel OS et tu utilises quelle version de Java et JavaFX ? J'ai du faire quelques aménagements pour Java et JavaFX 18 ; ex : le fait d'utiliser la version de JavaFX de Gluon car celle que tu as dans ton projet arrivait pas a initialiser Direct3D (je suis sous Windows). Il manque peut-etre des fichiers natifs. Et aussi l'ajout du fichier module-info.java a la racine de src:

      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      module memory {
          requires javafx.graphics;
          requires javafx.fxml;
          requires javafx.controls;
          requires java.logging;
          exports pack;
          opens pack to javafx.fxml;
      }
    • Tu devrais externaliser tes chaînes de caractères dans un fichiers externe et utiliser un ResourceBundle pour les charger (pour le contenu des fichiers FXML utiliser la notation i18n %<nom de la clé de la chaîne a traduire>), ca te permettrait de supporter plus facilement d'autres langues après et aussi d’éviter de hard coder du texte dans le code qui génère certains écrans de manière procédurale (ex : le choix de la difficulté). Si tu utilises SceneBuilder pour construire tes FXML, il te permet a la fois de crée tes clés d'internationalisations (clique sur la roue dentee tout a droit du champ Text et choisir "Replace with internalized String)" et d'avoir un aperçu en chargeant le fichier property (Menu Preview->Internationalization->Set Resource...).
    • Un soucis connexe : tu devrais creer une enum pour les valeurs de ta difficulté et ensuite retirer les chaînes internationalises pour l'affichage (ou avoir un renderer approprie pour la ComboBox). Évidement ça rendra la construction de la boite de dialogue un peu plus verbeuse mais l’idée est a conserver en tête pour plus tard.
    • A ce stade, le chargement de diff.fxml est redondant dans tous les niveaux de difficulté choisis.
    • Quelque soit le niveau de difficulté choisi, la méthode setupDiffX() fait strictement rien pour le moment.


    Ce qui amène au cœur du soucis : si on met du code dans par exemple setupDiff1() :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    public void setupDiff1() {
            n1.setVisible(false);
            n2.setVisible(false);
            n3.setVisible(false);
        }
    On a droit a une jolie NullPointerException :

    Code console : 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
    Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    	at javafx.fxml@18.0.2/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1857)
    	at javafx.fxml@18.0.2/javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1724)
    	at javafx.base@18.0.2/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
    	at javafx.base@18.0.2/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
    	at javafx.base@18.0.2/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    	at javafx.base@18.0.2/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    	at javafx.base@18.0.2/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    	at javafx.base@18.0.2/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    	at javafx.base@18.0.2/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    	at javafx.base@18.0.2/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    	at javafx.base@18.0.2/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    	at javafx.base@18.0.2/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    	at javafx.base@18.0.2/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    	at javafx.base@18.0.2/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
    	at javafx.base@18.0.2/javafx.event.Event.fireEvent(Event.java:198)
    	at javafx.graphics@18.0.2/javafx.scene.Node.fireEvent(Node.java:8797)
    	at javafx.controls@18.0.2/javafx.scene.control.Button.fire(Button.java:203)
    	at javafx.controls@18.0.2/com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:208)
    	at javafx.controls@18.0.2/com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274)
    	at javafx.base@18.0.2/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:247)
    	at javafx.base@18.0.2/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
    	at javafx.base@18.0.2/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
    	at javafx.base@18.0.2/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    	at javafx.base@18.0.2/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    	at javafx.base@18.0.2/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    	at javafx.base@18.0.2/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    	at javafx.base@18.0.2/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    	at javafx.base@18.0.2/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    	at javafx.base@18.0.2/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    	at javafx.base@18.0.2/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    	at javafx.base@18.0.2/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    	at javafx.base@18.0.2/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    	at javafx.base@18.0.2/javafx.event.Event.fireEvent(Event.java:198)
    	at javafx.graphics@18.0.2/javafx.scene.Scene$MouseHandler.process(Scene.java:3881)
    	at javafx.graphics@18.0.2/javafx.scene.Scene.processMouseEvent(Scene.java:1874)
    	at javafx.graphics@18.0.2/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2607)
    	at javafx.graphics@18.0.2/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:411)
    	at javafx.graphics@18.0.2/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:301)
    	at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    	at javafx.graphics@18.0.2/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:450)
    	at javafx.graphics@18.0.2/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:424)
    	at javafx.graphics@18.0.2/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:449)
    	at javafx.graphics@18.0.2/com.sun.glass.ui.View.handleMouseEvent(View.java:551)
    	at javafx.graphics@18.0.2/com.sun.glass.ui.View.notifyMouse(View.java:937)
    	at javafx.graphics@18.0.2/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    	at javafx.graphics@18.0.2/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184)
    	at java.base/java.lang.Thread.run(Thread.java:833)
    Caused by: java.lang.reflect.InvocationTargetException
    	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:116)
    	at java.base/java.lang.reflect.Method.invoke(Method.java:577)
    	at com.sun.javafx.reflect.Trampoline.invoke(MethodUtil.java:77)
    	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
    	at java.base/java.lang.reflect.Method.invoke(Method.java:577)
    	at javafx.base@18.0.2/com.sun.javafx.reflect.MethodUtil.invoke(MethodUtil.java:275)
    	at javafx.fxml@18.0.2/com.sun.javafx.fxml.MethodHelper.invoke(MethodHelper.java:84)
    	at javafx.fxml@18.0.2/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1852)
    	... 46 more
    Caused by: java.lang.NullPointerException: Cannot invoke "javafx.scene.Group.setVisible(boolean)" because "this.n1" is null
    	at memory/pack.SceneController.setupDiff1(SceneController.java:622)
    	at memory/pack.SceneController.jouer(SceneController.java:697)
    	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
    	... 53 more

    Et c'est normal ! Quand tu fais root = FXMLLoader.load(getClass().getResource("diff.fxml")); a la ligne 691 de SceneController.java (et chacune des lignes similaires qui suivent pour chacun des niveaux de difficulté), tu vas initialiser une toute nouvelle instance de la classe SceneController. Tu as donc desormais 2 copies actives de SceneController :
    • Celle initialisée par le chargement de accueil.fxml. Dans cette version, les valeurs déclarées dans diff.fxml ont toutes la valeur null.
    • Celle initialisée par le chargement de diff.fxml. Dans cette version, les valeurs déclarées dans diff.fxml sont bien initialisées (toutes les valeurs provenant de accueil.fxml ont toutes la valeur null) mais c'est pas cette instance que tu es en train de manipuler.


    Moralité : c'est pas forcement une idée géniale de tenter de partager un même contrôleurs entre plusieurs FXML, outres les potentiels effets de bord pas prévus dans le cas ou ça marcherai, en général le développeur oublie qu'il crée une nouvelle instance différente de celle dans laquelle il est a chaque fois qu'il invoque FXMLLoader.load().

    EDIT - ah oui j'oubliais aussi qu'il est pas recommandé d'utiliser la version statique de la méthode load() de la classe FXMLLoader. Il est plutôt recommandé de créer une nouvelle instance et d'invoquer la méthode d'instance load(), celle sans argument (entre autres car comme ça on peut aussi invoquer getController() juste après ce qu'on ne peut pas faire lorsqu'on utilise la version statique de la méthode).
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2022
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 20
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2022
    Messages : 11
    Points : 9
    Points
    9
    Par défaut
    Bonsoir, tout d'abord merci beaucoup pour cette réponse ça m'aide vraiment.

    J'ai utilisé GitHub de cette manière tout simplement car je ne sais pas du tout m'en servir, j'ai créé mon compte pour vous partager mon code, car je n'ai pas vraiment compris comment on en inséré dans la discussion, je veillerai à me renseigner.
    Je suis sous Windows11 et j'utilise la version 18.0.2.1 de Java et JavaFX 19. Je ne vais pas vous mentir (et vous avez du le constater) que je suis un grand débutant en développement (j'ai commencé en septembre en cours), Et forcément plusieurs soucis ressortent chez moi, notamment un majeur, l'optimisation, je suis juste très nul à ça donc je m'excuse ça a du être pas facile à déchiffrer parmi des lignes certainement inutiles.

    Pour ce qui est des deux points suivants je n'ai pas bien compris, je vais essayer de me renseigner auprès de mes professeurs et internet pour ne pas vous "monopoliser".

    Oui c'est vrai que pour l'instant, avoir plusieurs chargements possibles de diff.FXML est inutile, cependant c'est juste pour pouvoir appeler après une procédure selon le choix de la difficulté (setupDiffx()), cependant en y réfléchissant avec vos remarque, il serait plus judicieux d'appeler cette procédure avant le chargement du fichier, évitant ainsi divers soucis et en économisant des lignes de code.

    Pour le reste tout est clair maintenant, je vois l'erreur et en y repensant elle est tout bête. Il faudrait donc que je fasse nouveau controller pour chaque nouvelle page c'est ça ? (Un pour accueil.FXML et un pour diff.FXML)

    En tout cas je vous remercie encore pour le temps que vous avez pris à comprendre et répondre à mon problème cela m'aide beaucoup,

    Bonne soirée à vous.

  4. #4
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Août 2005
    Messages : 6 840
    Points : 22 854
    Points
    22 854
    Billets dans le blog
    51
    Par défaut
    J'ai édité mon message sans voir que tu avais répondu depuis et donc je vais te reposter ce que j'ai écrit au dessus :

    EDIT - ah oui j'oubliais aussi qu'il est pas recommandé d'utiliser la version statique de la méthode load() de la classe FXMLLoader. Il est plutôt recommandé de créer une nouvelle instance et d'invoquer la méthode d'instance load(), celle sans argument (entre autres car comme ça on peut aussi invoquer getController() juste après ce qu'on ne peut pas faire lorsqu'on utilise la version statique de la méthode).

    ----

    Par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    final var fxmlLoader = new FXMLLoader(...);
    final var monNoeud = fxmlLoader.<MyNode>load();
    final var monController = fxmlLoader.<MyNodeController>getController();
    ----

    Pour l'externalisation des chaînes, ça marche de manière suivante :

    • Créer un fichier texte.properties dans le package pack.
    • Ce fichier contient des clés associées a des chaînes de texte, par exemple :
      et d'autres encore pour tous les textes affichés a l'ecran.
    • Créer un ResourceBundle dans le code (c'est une classe un peu ancienne donc la résolution du chemin est un peu archaïque) :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      final var bundle = ResourceBundle.getBundle("pack/texte"); // Bien noter j'ai pas écrit "texte.properties"
    • Récupérer ensuite les bonnes valeurs avec les clés:
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      stage.setTitle(bundle.getString("app.title"));
    • Si tu fais une faute de frappe en saisissant ta clé de traduction ou si la clé est absente du fichier, une exception ResourceNotFoundException sera levée quand tu invoques bundle.getString()
    • Il t'est possible de spécifier des clés dans le FXML avec la notation %
      Code XML : Sélectionner tout - Visualiser dans une fenêtre à part
      <Button id="btnJouer" fx:id="btnJouer" layoutX="139.0" layoutY="175.0" mnemonicParsing="false" onAction="#jouer" prefHeight="54.0" prefWidth="222.0" styleClass="btn" text="%bouton.jouer" />
    • Et de rajouter dans texte.properties la valeur
      Code txt : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      app.name=Memory
      bouton.jouer=Jouer
    • Lors de la création du FXMLLoader il est possible de spécifier le ResourceBundle en second argument. Comme ca l'UI sera chargee avec les bonnes valeurs de texte.
    • Comme ca tu peux corriger tes fautes d’orthographe ou de grammaire ou carrément changer la valeur des chaînes de texte de ton application sans devoir aller taper dans le code
    • Maintenant imagine que tu veux envoyer ton jeu a qqun qui parle anglais et ne comprend pas du tout le français.
    • Tout ce que tu as a faire est de créer un nouveau fichier texte_en.properties dans le package pack, contenant :
      Code txt : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      app.name=Memory
      bouton.joue=Play
    • Si l'ordi de ton ami est configure pour l'anglais, les textes anglais s'afficheront automatiquement a la place des textes français au lancement du jeu.
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

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

Discussions similaires

  1. [SP-2007] Modifier les éléments d'une liste
    Par Djembadi dans le forum SharePoint
    Réponses: 5
    Dernier message: 26/06/2012, 11h43
  2. [IP-2007] Parcourir les éléments d'un groupe
    Par ludojojo dans le forum InfoPath
    Réponses: 2
    Dernier message: 08/08/2011, 11h30
  3. [Turbo Pascal] Modifier les éléments d'un fichier
    Par Mr Doudy dans le forum Turbo Pascal
    Réponses: 3
    Dernier message: 14/10/2008, 20h05
  4. Réponses: 3
    Dernier message: 02/07/2008, 11h52
  5. [CR 10] Séparer les éléments d'un groupe
    Par Giovanny Temgoua dans le forum SAP Crystal Reports
    Réponses: 7
    Dernier message: 07/04/2005, 14h36

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