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 :

Suivi de l'état d'avancement d'un service - Conflit avec des modifs de l'interface graphique du logiciel


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 Suivi de l'état d'avancement d'un service - Conflit avec des modifs de l'interface graphique du logiciel
    Bonjour,
    Je rencontre un problème dans l'utilisation d'un service dont je souhaite suivre l'état d'avancement.
    J'utilise un service pour exécuter une tâche de fond qui permet entre autre de charger des éléments dans l'interface graphique du logiciel avec une commande de ce style ("myAnchorPane.getChildren().add(inmportedNode);").

    J'ai besoin de pouvoir mettre à jour le statut de progression de la tâche. J'utilise pour cela les fonction updateMessage() et updateProgress() de mon service. Une barre de progression est mise à jour lorsque le statut de progression de la tâche change.
    Même si il n'est pas directement utilisable , voici un extrait de mon code :

    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
     
    taskProgressionBorderPane.startTask();
    final Service<Void> importFileService = new Service<Void>() {
    			@Override
    			protected Task<Void> createTask() {
    				return new Task<Void>() {
    					@Override
    					protected Void call() throws Exception{
     
    						Platform.runLater(() -> {
    						    updateMessage("Check System");
    					    	    checkSystemModel(file);
    					    	    updateProgress(0.1,1.0);
     
    						    updateMessage("Import node framework from file");
    					    	    rootLayout.openDataFile(file);    // routine contenant une instruction de type "myAnchorPane.getChildren().add(inmportedNode);"
    					    	    updateProgress(0.2,1.0);
    						});
     
    					return null;
    					}
    				};
    			}
        	};
     
        	taskProgressionBorderPane.getTaskProgressionDoubleProperty().bind(importFileService.progressProperty());
        	taskProgressionBorderPane.getTaskStatusStringProperty().bind(importFileService.messageProperty());
        	importFileService.start();
        	importFileService.stateProperty().addListener(obs->{
        		switch (importFileService.getState()) {
        		case SUCCEEDED:
        			taskProgressionBorderPane.stopTask();
        			break;
        		case FAILED:
        			System.out.println("Task failed");
        			break;
        		}				
    		});
    Le problème que je rencontre c'est que le programme fonctionne lorsque j'utilise dans la tâche la commande Platform.runLater(() -> { liste d'instructions });, mais à ce moment, le suivi du status de progression de la tâche n'est plus correctement transmis par les instructions
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    taskProgressionBorderPane.getTaskProgressionDoubleProperty().bind(importFileService.progressProperty());
    taskProgressionBorderPane.getTaskStatusStringProperty().bind(importFileService.messageProperty());

    En supprimant l'instruction "Platform.runLater(() -> "... . Le suivi de progression fonctionne correctement, mais la tâche échoue. Le problème intervient lorsque je charge dans un AnhorPane un noeud graphique ("myAnchorPane.getChildren().add(inmportedNode);"). Cette instruction n'étant pas bloquante lorsque "Platform.runLater" est utilisé.

    Je ne comprends pas vraiment cette différence de comportement.
    Votre aide pour solutionner ce problème me serait bien utile.
    Merci d'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
    J'entrevoit 2 soucis :
    1. Tu modifies le contenu de la scène qui est visible a l’écran. Or ceci ne peut être fait que sur le JavaFX Application Thread. D’où le plantage que tu as (même si tu n'a pas copie ton exception. je rappelle que le service te permet de renvoyer l'erreur en cas de besoin).

      Tu peux manipuler des contrôles dans un thread différent tant qu'ils ne sont pas visibles mais ça peut poser des soucis pour les calculs de dimensions ou les styles car le contrôle n'a pas encore été "réalisé"/finalisé (certaines opérations de mise en page ne sont faites qu’après le tout premier affichage).

      Par contre a partir du moment ou tu les affiches dans une scène visible, pas de choix il faut que ca se fasse sur le JavaFX Application Thread sinon dans 80% des cas, ça mènera a des exceptions et plantages car le scenegraphe fait un check qu'il est sur le bon thread avant de faire l’opération. D'ou la nécessite de faire un Platform.runLater().
    2. Ce qui mène alors au second soucis : les deux opérations ne sont plus synchrones et donc le chargement peut se faire bien après que la progression ait eut lieu. Dans ce cas tu n'as pas vraiment de choix : il te faut mettre decouper ta tache plus finement pour separer la partie a lancer sur le JavaFX Application Thread. Quelque chose dans le 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
      importFileService = new Service<Void>() {
      			@Override
      			protected Task<Void> createTask() {
      				return new Task<Void>() {
      					@Override
      					protected Void call() throws Exception{
      						updateMessage("Check System");
          						checkSystemModel(file);
      						updateProgress(0.1,1.0);
      						updateMessage("Import node framework from file");
      						//rootLayout.openDataFile(file);    // routine contenant une instruction de type "myAnchorPane.getChildren().add(inmportedNode);"
      						// Decouper la routine en separant le chargement de importedNode de l'instruction add();
      						Node importedNoed = [...]                                                    
      						Platform.runLater(() -> myAnchorPane.getChildren().add(inmportedNode));
      						updateProgress(0.2,1.0);
      						return null;
      					}
      				};
      			}
          	};
      Si jamais le suivi de l'operation est encore incorrect après, on pourra tenter d'introduire une pause dans la tache (wait()) qui devrai etre reveillee une fois le noeud ajoute dans la scene (notify()).
    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

Discussions similaires

  1. Bubuntu 9.04 - État d'avancement
    Par srvremi dans le forum Bubuntu
    Réponses: 2
    Dernier message: 30/04/2009, 22h10
  2. Affichage de l'état d'avancement en temps réel
    Par welou dans le forum Forms
    Réponses: 1
    Dernier message: 18/05/2008, 02h18
  3. Réponses: 5
    Dernier message: 14/12/2005, 09h28
  4. état d'avancement d'un CopyFile()
    Par Xam335 dans le forum C++Builder
    Réponses: 7
    Dernier message: 23/09/2005, 11h12
  5. [SAX] Parser SAX : connaitre l'état d'avancement
    Par GLA31 dans le forum Format d'échange (XML, JSON...)
    Réponses: 3
    Dernier message: 26/10/2004, 09h08

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