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 :

Interface graphique qui rame / taches de fonds


Sujet :

JavaFX

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2015
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2015
    Messages : 3
    Points : 1
    Points
    1
    Par défaut Interface graphique qui rame / taches de fonds
    Bonjour à tous ,

    Je suis actuellement en train de développer une interface graphique composée entre autre d'une tableView , d'un textArea, d'un barChart ainsi que d'un panel contenant plusieurs progressIndicator. J’exécute en tache de fond une certains nombre de traitement sur des données que j'ai récupéré auparavant afin ensuite de pouvoir afficher les résultats sur l'interface.
    Pour chacune des données récupérée , j’exécute 6 taches .
    Chacune de ces taches est exécutée via une classe CustomTask que j'ai crée et qui hérite de la classe Task. Ces taches vont exécuter des lignes de commande via un Processbuilder ( commande clearCase, execution de . bat , execution de . exe) .
    Pour chaque donnée les taches doivent être faite de manière séquentielle . Les données doivent aussi être traité l'une après l'autre .

    Voici la fonction me permettant de lancer le traitement de mes donné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
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
     
    public void launchTasks()
         {
     
     
        final CustomTask task1= new CustomTask(cmdPrompt,cmd,Namescript);
        final CustomTask task2= new CustomTask(cmdPrompt,cmd2,Namescript);
        final CustomTask task3= new CustomTask(cmdPrompt,cmd3,Namescript);
        final CustomTask task4= new CustomTask(cmdPrompt,cmd4,Namescript);
        final CustomTask task5= new CustomTask(cmdPrompt,cmd5,Namescript);
        final CustomTask task6= new CustomTask(cmdPrompt,cmd6,Namescript);
     
        pi1.progressProperty().bind(task3.progressProperty());
        pi2.progressProperty().bind(task4.progressProperty());
        pi3.progressProperty().bind(task5.progressProperty());
        pi4.progressProperty().bind(task6.progressProperty());
        new Thread(task1).start();
        task1.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
     
                    @Override
                    public void handle(WorkerStateEvent t) {
     
                            new Thread(task2).start();
                    }
                });
     
     
        task2.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
     
                        @Override
                        public void handle(WorkerStateEvent t) {
     
                                new Thread(task3).start();
                        }
                    });
     
       task3.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
     
                        @Override
                        public void handle(WorkerStateEvent t) {
     
                                new Thread(task4).start();
                        }
                    });
       task4.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
     
                        @Override
                        public void handle(WorkerStateEvent t) {
     
                                new Thread(task5).start();
                        }
                    });
            task5.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
     
                        @Override
                        public void handle(WorkerStateEvent t) {
     
                                new Thread(task6).start();
                        }
                    });
     
       task6.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
     
                        @Override
                        public void handle(WorkerStateEvent t) {
                             //mise à jour de la tabelView 
                                   // on check si il y encore des données a traiter 
                                                   // si oui   on rappelle la fonction  launchTasks(), pour la prochaine donnée   
                                                  // sinon on a fini 
                        }
                    });
    }
    Comme vous pouvez le voir j’attends toujours la fin d'une tache avant d'en exécuter une autre . La méthode launchTasks est appelé récursivement afin de traiter la suite des données . A chaque appel la méthode traite une donnée choisie dans une liste d'objets par l’intermédiaire d'un conteur ( j'ai retiré cette portion de code car il s'agit juste de récupération de données pour pouvoir mettre en place les commande avant le lancement de la première tache) .

    Voici ma classe CutomTask qui me permet d’exécuter ma ligne de commande puis de rediriger le flux vers le textArea de mon interface :
    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
     
    public class CustomTask extends Task {
     
        private String contenu="" ;
        private TextArea cmdPrompt;
        private String [] myCmd;
        private String scriptName;
     
     
        public CustomTask(TextArea cmdProm, String[] cmd, String name)
        {
            this.cmdPrompt=cmdProm;
     
            this.myCmd=cmd;
            this.scriptName=name;
            messageProperty().addListener(new ChangeListener<String>(){
     
                @Override
                public void changed(ObservableValue<? extends String> arg0,
                        String arg1, String arg2) {
                    cmdPrompt.appendText(contenu);
     
                }});
     
     
     
     
     
        }
        @Override
        protected Object call()  {
     
        try {  
            TestExecution.probuilder.command(myCmd);
            Process p=TestExecution.probuilder.start();   
     
            BufferedReader input= new   BufferedReader(newInputStreamReader(p.getInputStream()));
            String line;
            String tmpon="";
            tmpon=("\n ");
            while ((line = input.readLine()) != null)
              {
               tmpon = tmpon+"\n"+line;
               System.out.println(line);
              }
            contenu=tmpon;
            input.close();
            p.waitFor();
          }
         catch (Exception e) {
           System.out.println("Task Exception");
         }
     
             updateMessage(contenu);
             updateProgress(1, 1);
             return null;
        }
        }

    J'arrive a traiter l'ensemble de mes données mais après un certains nombre de lancements (~5) de la méthode launchTasks() , l'interface commence à très sévèrement ramer . Il devient très difficile de naviguer au niveau de la tableView , les progressIndicator sont aussi très ralenti . Même chose pour le textArea . L'interface rame vraiment beaucoup .Même après l’exécution de tous les taches de fonds, l'interface reste dans le même étant. Ce n'est pas un problème de thread , étant donnée que je fais en sorte de lancer une tache , un fois la précédente terminée.
    J'ai pensé que c'était la récursivité qui entrainait mon problème mais après avoir essayé sans , le problème persiste.

    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 870
    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 870
    Points : 22 933
    Points
    22 933
    Billets dans le blog
    53
    Par défaut
    Bon sans pouvoir tester, quelques idées en vrac :

    • Task s'utilise avec Service pas avec Thread
    • Donc du coup on bind pas sur la propriété progress de la tache mais sur celle du Service.
    • Donc du coup les notifications d'événement de la propriété progress seront faites dans le JavaFX Application Thread au lieu de chaque threads ici.
    • Même chose avec la propriété message qui est ici manipulée directement dans la tache et en plus pas dans le bon thread (faut invoquer Platform.runLater()). Un bémol cependant, une remontée des messages via la propriété message du service pourrait faire qu'on en perdre car pour éviter de noyer le JavaFX Application Thread, certains sont éliminés (même chose avec les autres propriété mais elles sont moins critiques). Donc, comme toi tu veux avoir l'intégralité du contenu, l'idée ici est dans la tache de gérer un buffer (List<String> ou StringBuilder) qu'on construit au fur et à mesure de l'avancement de la tache et qu'on met à jour un peu moins souvent dans le contrôle cible quand il dépasse un certaine taille (et à la fin de la tache également). La propriété message ne servant ici qu'à mettre à jour des éléments non critiques de l'UI (label associé à la barre de progression) qui eux peuvent se permettre de sauter des valeurs.
    • Si c'est séquentiel, à quoi ça sert de lancer 6 threads différents alors qu'1 service avec 1 seule tache qui fait 6 gestions identiques des scripts semble bien plus approprié ?

  3. #3
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2015
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2015
    Messages : 3
    Points : 1
    Points
    1
    Par défaut
    Merci pour ces différentes suggestions. J'ai changé mon code en utilisant un objet Service pour lancer mes taches. J'ai également fait en sorte de lancer mes 6 traitements dans une seule et même tache . Cependant le problème est toujours là. J'ai fais quelques test et j'ai constaté que lorsque je n'utilise pas de processbuilder je n'ai aucun problème de ralentissement. Ce pourrait il que ce soit le fait que j'utilise le processbuilder de manière intensive qui soit a l'origine de mon problème ?

  4. #4
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 870
    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 870
    Points : 22 933
    Points
    22 933
    Billets dans le blog
    53
    Par défaut
    Tu ne sembles pas consommer les flux de sortie standard et d'erreur standard de ton processus. Pas plus que tu ne vérifies la valeur de retour du processus. Est-ce normal ?

    EDIT - mal lu.

  5. #5
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 870
    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 870
    Points : 22 933
    Points
    22 933
    Billets dans le blog
    53
    Par défaut
    Un peu mieux réveillé. Cela vient peut-etre de la manière dont tu construits tes messages vu que tu concatènes des chaines (et donc que tu construits tout une foultitude d'objets intermédiaires). Est-ce que ceci marche mieux pour toi, en adaptant les commandes a ton OS/ce que tu veux exécuter :

    Code Java : 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
    74
    75
    76
    77
    78
    79
    80
    package test;
     
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.PrintStream;
    import java.io.Reader;
    import java.util.Objects;
    import javafx.application.Platform;
    import javafx.concurrent.Task;
    import javafx.scene.control.TextArea;
     
    final class CustomTask extends Task<Void> {
     
        static final class ProcessDescription {
     
            public String[] command;
            public String name;
            public int expResult = 0;
        }
     
        private final StringBuilder outMessageBuilder = new StringBuilder();
        private final StringBuilder errMessageBuilder = new StringBuilder();
        private final TextArea cmdPrompt;
        private final ProcessDescription[] myCmd;
     
        public CustomTask(final TextArea cmdProm, final ProcessDescription... cmd) {
            Objects.requireNonNull(cmdProm);
            Objects.requireNonNull(cmd);
            this.cmdPrompt = cmdProm;
            this.myCmd = cmd;
        }
     
        @Override
        protected Void call() throws Exception {
            final int totalProgress = myCmd.length;
            int progress = 0;
            updateProgress(progress, totalProgress);
            for (final ProcessDescription processDescription : myCmd) {
                updateTitle(processDescription.name);
                runProcess(processDescription);
                updateProgress(++progress, totalProgress);
                if (isCancelled()) {
                    return null;
                }
            }
            return null;
        }
     
        private void runProcess(final ProcessDescription processDescription) throws IOException {
            try {
                final ProcessBuilder processBuilder = new ProcessBuilder(processDescription.command);
                final Process process = processBuilder.start();
                consumeProcessOutput(process.getInputStream(), outMessageBuilder, System.out);
                consumeProcessOutput(process.getErrorStream(), errMessageBuilder, System.err);
                final int errorCode = process.exitValue();
                if (errorCode != processDescription.expResult) {
                    throw new IllegalStateException();
                }
                updateMessage(outMessageBuilder.toString());
            } finally {
                Platform.runLater(() -> {
                    cmdPrompt.setText(outMessageBuilder.toString());
                    cmdPrompt.positionCaret(cmdPrompt.getText().length());
                });
            }
        }
     
        private void consumeProcessOutput(final InputStream source, final StringBuilder messageBuilder, final PrintStream out) throws IOException {
            try (final Reader inputReader = new InputStreamReader(source); final BufferedReader input = new BufferedReader(inputReader)) {
                String line;
                while ((line = input.readLine()) != null) {
                    messageBuilder.append(line);
                    messageBuilder.append('\n'); // NOI18N.
                    out.println(line);
                }
            }
        }
    }

    Code Java : 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
    package test;
     
    import javafx.application.Application;
    import javafx.concurrent.Service;
    import javafx.concurrent.Task;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.control.ProgressBar;
    import javafx.scene.control.TextArea;
    import javafx.scene.control.ToolBar;
    import javafx.scene.layout.BorderPane;
    import javafx.stage.Stage;
     
    public final class Main extends Application {
     
        @Override
        public void start(Stage primaryStage) {
            final TextArea textArea = new TextArea();
            textArea.setEditable(false);
            final ProgressBar progressBar = new ProgressBar();
            progressBar.setMaxWidth(Double.MAX_VALUE);
            progressBar.setProgress(0);
            final Button startButton = new Button();
            startButton.setText("Start");
            startButton.setOnAction(actionEvent -> {
                startButton.setDisable(true);
                final Service<Void> service = new Service<Void>() {
     
                    @Override
                    protected Task<Void> createTask() {
                        final CustomTask.ProcessDescription p1 = new CustomTask.ProcessDescription();
                        p1.name = "CMD Help";
                        p1.command = new String[]{"cmd", "/?"};
                        p1.expResult = 1;
                        final CustomTask.ProcessDescription p2 = new CustomTask.ProcessDescription();
                        p2.name = "DIR";
                        p2.command = new String[]{"cmd", "/c", "dir"};
                        final CustomTask.ProcessDescription p3 = new CustomTask.ProcessDescription();
                        p3.name = "Condor_status";
                        p3.command = new String[]{"C:\\condor\\bin\\condor_status"};
                        // Remvoie une tres longue chaine au format XML.
                        final CustomTask.ProcessDescription p4 = new CustomTask.ProcessDescription();
                        p4.name = "Condor_status";
                        p4.command = new String[]{"C:\\condor\\bin\\condor_status", "-xml"};
                        return new CustomTask(textArea, p1, p2, p3, p4);
                    }
                };
                progressBar.progressProperty().bind(service.progressProperty());
                service.setOnSucceeded(workerStateEvent -> startButton.setDisable(false));
                service.setOnFailed(workerStateEvent -> {
                    startButton.setDisable(false);
                    System.err.println(workerStateEvent.getSource().getException());
                });
                service.start();
            });
            final ToolBar toolBar = new ToolBar(startButton);
            final BorderPane root = new BorderPane();
            root.setTop(toolBar);
            root.setCenter(textArea);
            root.setBottom(progressBar);
            final Scene scene = new Scene(root, 800, 600);
            primaryStage.setTitle("Test");
            primaryStage.setScene(scene);
            primaryStage.show();
        }
     
        public static void main(String[] args) {
            launch(args);
        }
    }

  6. #6
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2015
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2015
    Messages : 3
    Points : 1
    Points
    1
    Par défaut
    J'ai modifié quelque peu mon code en m’inspirant de ce que tu m'a donné. Cela m'a permis d'avoir quelque chose de plus clean ( merci ) . Mais le problème est toujours là. Le problème de ralentissement vient en effet de la redirection du flux issu de mes Process vers mon TextArea . En l'enlevant , l'interface graphique est tout à fait fluide.

  7. #7
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 870
    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 870
    Points : 22 933
    Points
    22 933
    Billets dans le blog
    53
    Par défaut
    Donc ça pourrait être une fréquence de mise à jour trop importante et/ou une taille de texte trop importante.

Discussions similaires

  1. [Débutant] interface graphique qui prend un fichier comme input
    Par ibtissem88 dans le forum Interfaces Graphiques
    Réponses: 4
    Dernier message: 19/03/2013, 12h15
  2. Réponses: 1
    Dernier message: 29/03/2012, 18h51
  3. Interface graphique qui bouge verticalement
    Par loic_1715 dans le forum AWT/Swing
    Réponses: 6
    Dernier message: 29/05/2011, 20h30
  4. [Icon] Librairie qui permet de faire des interfaces graphiques
    Par kespy13 dans le forum Autres langages
    Réponses: 1
    Dernier message: 25/10/2007, 19h25
  5. fond d'interface graphique
    Par tasshil dans le forum AWT/Swing
    Réponses: 3
    Dernier message: 16/04/2007, 21h38

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