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 :

Propagation des modifications à d'autres élément contenus dans une liste


Sujet :

JavaFX

  1. #1
    Membre du Club
    Homme Profil pro
    Ingénieur projet
    Inscrit en
    Juin 2014
    Messages
    46
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Ingénieur projet
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2014
    Messages : 46
    Points : 43
    Points
    43
    Par défaut Propagation des modifications à d'autres élément contenus dans une liste
    Bonjour,
    Je rencontre un problème dans la mise en place de listeners.
    J'affiche dans une listView (speciesListListView) le nom d'une liste de composés (Compose.getNomCompose()). L'ensemble des composés est contenu dans la liste mergedComposeList. Dans cette liste, il peut exister des éléments qui portent le même nom, mais qui sont associées à des réactions différentes ((String) compose.getNomReactionAssociee()). Exemple A-Reaction 1 et A-Reaction 2

    Lorsque je clique sur un des éléments listés dans speciesListListView, une liste de valeurs contenue dans ((DoubleProperty) compose.getTimeField()) est affichée dans une tableView (speciesConcentrationsTableView). L'utilisateur a alors la possibilité d'apporter des modifications à cette série de données directement dans le tableau.

    Voici ce que je cherche à faire : lorsque des modifications sont apportées à compose.getTimeField(), je dois vérifier si dans la liste mergedComposeList il n'y a pas des composés qui portent le même nom. Si c'est le cas, je dois propager les modifications apportées.

    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
     
                    checkNodeListListView.setListOfCompose(mergedComposeList);
     
                    // Utilisation d'un listener permettant de détecter lorsque l'utilisateur clique sur l'un ou l'autre des composés contenus dans speciesListListView
    		speciesListListView.getSelectionModel().selectedItemProperty().addListener((changed, oldCompose, newCompose) -> {
     
    			checkNodeListListView.checkComposeInjectionNode(newCompose);
                            // Mise à jour du contenu de la tableView speciesConcentrationsTableView lorsque l'utilisateur sélectionne un composé
    			speciesConcentrationsTableView.updateConcentrationTable(newCompose);
     
    			ListChangeListener<DoubleProperty> timeFieldListener = new ListChangeListener<DoubleProperty>(){
    				@Override
    				public void onChanged(Change <? extends DoubleProperty> c) {
     
    					while (c.next()){
    						System.out.println("Modif occured in TimeField of "+ newCompose.getNomCompose() + "index : "+ c.getFrom());
    						if (c.wasAdded()){
    							System.out.println("Added value");
    							for (Compose compItem : listOfReactiveCompose){
    								if (compItem.getNomCompose() == newCompose.getNomCompose() && compItem.getNomReactionAssociee() != newCompose.getNomReactionAssociee()){
    									//Un doublon a été détecté, la modification est propagée.
     
    									for (DoubleProperty addedElement : c.getAddedSubList()){
    										if (compItem.getTimeField().size() == 0 | (compItem.getTimeField().size() > 0 && compItem.getTimeField().size() <= c.getFrom())){
    											compItem.getTimeField().add(addedElement);
    										}else{
    											compItem.getTimeField().set(c.getFrom(), addedElement);
    										}
    									}
    								}
    							}
    						}else if (c.wasRemoved()){
    							System.out.println("Removed value");
    							for (Compose compItem : listOfReactiveCompose){
    								if (compItem.getNomCompose() == newCompose.getNomCompose() && compItem.getNomReactionAssociee() != newCompose.getNomReactionAssociee()){
    									// Un doublon a été détecté, la modification est propagée.
     
    									for (DoubleProperty removedElement : c.getRemoved()){										
    										compItem.getTimeField().remove(c.getFrom());
    									}
    								}
    							}
    						}
    					}
     
    				}
    			};
     
    			if (oldCompose != null){
    				System.out.println("Listener removed from "+ oldCompose.getNomCompose() + " -> "+ oldCompose.getNomReactionAssociee());
    				newCompose.getTimeField().removeListener(timeFieldListener);
    			}
     
    			System.out.println("Listener added to "+ newCompose.getNomCompose() + " -> "+ newCompose.getNomReactionAssociee()); 
    			newCompose.getTimeField().addListener(timeFieldListener);
     
    		});
    En procédant de la sorte, la propagation des modifications apportées à la série de données fonctionne. Les modifications apportées au composé A-Reaction 1 sont bien propagées à A-Reaction 2.
    Le problème c'est que si je viens à apporter des modifications au composé doublon (A-Reaction 2), je tombe dans une boucle infinie. Les modifications apportées à A-Reaction 2 sont propagées à A-Reaction 1, mais comme A-Reaction 1 est modifié, le programme cherche à modifier A-Reaction 2, et ainsi de suite ...
    Du coup, j'avais tenté de désactiver le listener placé sur A-Reaction 1 lorsque A-Reaction 2 est sélectionné via la commande ci-dessous. Mais ça ne change pas le problème.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if (oldCompose != null){
        System.out.println("Listener removed from "+ oldCompose.getNomCompose() + " -> "+ oldCompose.getNomReactionAssociee());
        newCompose.getTimeField().removeListener(timeFieldListener);
    }
    Auriez vous des idées pour contourner ce problème.
    Merci par avance.

  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
    Alors j'ai absolument rien compris a l'explication et comme toujours ca aurait ete beaucoup plus simple avec un test simplifie demontrant le soucis (parceque grosso modo le fait que ca soit une ListView dans une UI importe pas du tout).

    Pour éviter des événements en cascade bouclant, pas 36 solutions :
    • Mettre un sémaphore :

      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      private boolean isEditing = false;
       
       
      [...]
      if (isEditing) {
         return;
      }
      isEditing = true;
      try {
          [...]
      } finally {
          isEditing = false;
      }
    • Ou desenregistrer/re-enregister les listeneurs.

      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      private TrucListener listener = [...]
       
       
      propriete.removeListener(listener);
      try {
          [...]
      } finally {
          propriete.addListener(listener);
      }
      Par fan ce cette dernière solution car changer l'ordre des listeneurs inscrits sur une propriété peut mener a d'autres soucis (par exemple si un listeneur placé plus tard dans la liste faisait un consume() de l'event).
    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
    Membre du Club
    Homme Profil pro
    Ingénieur projet
    Inscrit en
    Juin 2014
    Messages
    46
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Ingénieur projet
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2014
    Messages : 46
    Points : 43
    Points
    43
    Par défaut
    Bonjour, Désolé de revenir tardivement vers vous, encore une fois Mr Bouye a la solution a tous nos problèmes.
    L'intégration d'un sémaphore m'a effectivement permis de contourner mon problème de listeners en cascade.
    Et effectivement, maintenant que j'ai la solution, ça me paraît tellement évident ...
    C'est toujours bien de prendre un peu de recul ou d'avoir un avis extérieur.
    Merci et bonne journée.

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

Discussions similaires

  1. Réponses: 10
    Dernier message: 20/09/2019, 22h36
  2. Réponses: 3
    Dernier message: 08/10/2010, 12h42
  3. Récupération des éléments sélectionner dans une liste
    Par Jasmine80 dans le forum Interfaces Graphiques
    Réponses: 13
    Dernier message: 17/09/2009, 12h52
  4. Réponses: 9
    Dernier message: 24/06/2008, 09h45

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