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 :

résoudre problème Not on FX application thread


Sujet :

JavaFX

  1. #1
    Membre éclairé Avatar de Hind4Dev
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Novembre 2014
    Messages
    428
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2014
    Messages : 428
    Par défaut résoudre problème Not on FX application thread
    j'essai d'afficher un tableView contenant des boutons, dont chaque ligne est un objet thread, mais je reçoit l'erreur
    Not on FX application thread; currentThread = Thread-4
    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
     
    Runnable serverTask = () -> {
     
                    try {
                        srv = new ServerSocket(Integer.valueOf(txtPort.getText()));
     
     
                        for (int i = 0; i < nbrParticipants; i++) {
                            //un nouveau thread participant 
                            Participant Ui;         
                            socket = srv.accept();
                            JFXButton btn = new JFXButton();
                            Ui = new Participant(nonce, socket, "Connecté...");
                            Ui.setButton(btn);
                            //ajouter le participant venu à la liste
                            participants.add(Ui);
     
     
                            //lancement du thread du nouveau participant
                            Thread thread = new Thread(Ui);
                            thread.start();
     
     
                            //rafraichir le tableau
                            fillTable();
                    }                } catch (IOException e) {
                        e.printStackTrace();
                    }
    }
    Thread serverThread = new Thread(serverTask);
    serverThread.start();
    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
     
    public void fillTable() {
    //convertir liste en ObservableList
    connectedParticipants = FXCollections.observableArrayList(participants);
    //ajouter une action au boutons
            for (int i = 0; i < connectedParticipants.size(); i++) {
                final int index = connectedParticipants.get(i).getId();
                connectedParticipants.get(i).getButton().setOnAction(new EventHandler<ActionEvent>(){
                    @Override
                    public void handle(ActionEvent event) {
                        receivePi(index);
                        calculateQiPoints(index);
                    }
                });
            }
    //code pour les autres colonnes et l'ajout au tableView
    }
    Merci

  2. #2
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 900
    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 900
    Billets dans le blog
    54
    Par défaut
    Comme indiqué explicitement par l'erreur, la mise à jour de la table doit être faite sur le thread JavaFX. Par exemple en invoquant Platform.runLater().
    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 éclairé Avatar de Hind4Dev
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Novembre 2014
    Messages
    428
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2014
    Messages : 428
    Par défaut
    Il ne l'accepte pas Platform.runLater(), car la méthode que j'invoque est dans la classe initiale, non pas dans une classe Runnable de cette façon

    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
     
    public class DealerController implements Initializable {
     
           public synchronized void runServer() {
                 //ici je démarre le serveur et crée les threads sockets en les acceptant
                 Runnable serverTask = () -> { 
                        ... 
                  fillTable(); //appel de méthode qui produit un changement dans la fenêtre
                 }
           }
     
          //la méthode invoquée
          public synchronized void fillTable() {}
     
    }

  4. #4
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 900
    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 900
    Billets dans le blog
    54
    Par défaut
    Et donc ?

    Dans ce cas il faut s'arranger a ce qu'il ait accès a cette méthode (par exemple via une reference de methode), par exemple en permettant au controlleur de recevoir une action a invoquer losrque le chargement a eut lieu.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public void fillTable() {
      Optional<Whatever> action = Optional.ofNullable(getPostLoadAction());
      action.ifPresent(a -> {
                 if (! Platform.isFxApplicationThread()) {
                     Platform.runLater(() -> a.doStuff());
                 } else {
                     a.doStuff();
                 }
      });
    }
    D'ailleurs pourquoi elle est synchronisee cette méthode ? Il y a une bonne raison a cela ?
    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

  5. #5
    Membre éclairé Avatar de Hind4Dev
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Novembre 2014
    Messages
    428
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2014
    Messages : 428
    Par défaut
    merci bouye, mais je n'ai rien compris dans votre exemple de code. pour le synchronized, la méthode est appelée dans une création de threads le Runnable serverTask.

  6. #6
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 900
    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 900
    Billets dans le blog
    54
    Par défaut
    Ca n'explique en rien pourquoi elle est synchronisée. As-t-elle besoin de l’être ?

    Désolé mais je ne peux pas être plus clair avec le peu de code ou d'infos que tu as posté. En l’état rien n’empêche l'invocation de fillTable() (qui ne fait absolument rien on est bien d'accord).

    Tu as chargé tes donnée, on peut donc supposer que tu as genre une List<Toto>, un Set<Toto>, un Stream<Toto> ou Toto[] (ou un autre truc du même genre) sous la main. Tu veux dois désormais mettre a jour ta vue graphique dans une table sans doute (vu le nom de la méthode) ? Or cette table est uniquement disponible dans la classe Application ??? C'est bien ça ?
    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

  7. #7
    Membre éclairé Avatar de Hind4Dev
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Novembre 2014
    Messages
    428
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2014
    Messages : 428
    Par défaut
    c'est bien ça bouye, dans la méthode runServer() je démarre un serveur en instanciant ServerSocket et je crée un thread pour chaque client en lamdaExpression Runnable serverTask, les objets threads sont mis dans une liste chaque fois qu'un d'eux se connecte. Pour ce qui est de la méthode fillTable() dans l'Application, je suis entrain d'afficher un TableView depuis la liste des threads, contenant l'état du client connecté/déconnecté et un bouton pour chacun pour envoi de données, cette table doit être mise à jour chaque fois qu'un nouveau client arrive, voilà pourquoi je l'invoque là.

    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
     
    public synchronized void runServer() {
            Runnable serverTask = () -> {                
                    try {
                        //création de la ServerSocket
                        srv = new ServerSocket(Integer.valueOf(txtPort.getText()));
     
                        for (int i = 0; i < nbrParticipants; i++) {
                            //un nouveau participant venu
                            Participant Ui;         
                            //serveur accepte la connexion d'un participant
                            socket = srv.accept();
                            Ui = new Participant(socket);
     
                            //ajouter le participant venu à la liste
                            participants.add(Ui);
     
                            //lancement du thread du nouveau participant
                            Thread thread = new Thread(Ui);
                            thread.start();
     
                            //rafraichir le tableau
                            fillTable();
                       }               
                } catch (IOException e) {
                        e.printStackTrace();
                 }
           };
            Thread serverThread = new Thread(serverTask);
            serverThread.start();
    }

  8. #8
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 900
    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 900
    Billets dans le blog
    54
    Par défaut
    Oui mais tu dois réfléchir un peu plus de manière fonctionnelle et réactif en découplant tous tes process pour les rendre indépendant (et optionnels) les uns des autres.

    Par exemple ( y a plein d'autres manières de faire) :
    • Tu récupères ta liste de toto.
    • Si on t'as fourni une action a effectuer a la fin du traitement, tu l’exécutes.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // Ceci est invoque lorsqu'on a reçu une nouvelle liste.
    private Consumer<List<Toto>> onFinished = null;
     
    public void setOnFinished(Consumer<List<Toto>> value) {
        this.onFinished = value;
    }
     
    private void runServer() {
        // Mettre a jour la liste.
        List<Toto> list = [...]
        // Si on peut faire quelque chose a la fin alors le faire.
        Optional.ofNullable(onFinished)
                   .ifPresent(c -> c.accept(list));
    }
    Ailleurs (dans ta classe application ici)
    • tu vérifie que tu es dans le bon thread
    • si ce n'est pas le cas, tu te mets dans le bon thread.
    • tu effectues le traitement demander a savoir mettre la liste dans la table (ou je sais pas ou).


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    private void updateTotoTable(final List<Toto> list) {
        if (! Platform.isJavaFXThread()) {
             Plaform.runLater(() -> updateTotoTable(list);
             return;
        }
        // Remplir la table.
        [...]
    }
    Et a un moment tu enregistre cette méthode sur le contrôleur pour que la réaction puisse se produire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    controller.setOnFinished(this::updateTotoTable);
    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

  9. #9
    Membre éclairé Avatar de Hind4Dev
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Novembre 2014
    Messages
    428
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2014
    Messages : 428
    Par défaut
    CE que j'ai compris d'après ton code, que j'ai besoin d'apprendre deux choses dont je n'ai jamais travaillé avec, le pattern consumer/producer en java et la bibliothèque Optional. Je vais commencer à apprendre ça tout de suite puis on verra. Merci beaucoup bouye.

  10. #10
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 900
    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 900
    Billets dans le blog
    54
    Par défaut
    Et pourtant pour le premier ça fait déjà des années que tu le pratique en enregistrant des listeners ici et la qui ne sont qu'une application parmi d'autre du pattern observateur. Et si tu vois des gens qui s’égosillent et s'excitent autour de la programmation réactive (Rx) qui est aussi une application du pattern observateur ben c'est la même chose : un vieux concept remis au goût du jouer et appliqué a un champ différent ou plus large. Et pour info JavaFX fait déjà du Rx avec le binding.

    Pour Optional, ça sert principalement a éviter les tests foo == null et a pouvoir manipuler des valeurs vides mais jamais null pour éviter des NullPointerException grace a Optional.empty() et Optinal.ofNullable(). Idem pour les littéraux (voir OptionalInt).
    C'est un peu comme Objects.isNull(), Objects.nonNull() et Objects.requireNonNull(), on peut tres bien faire sans mais ces API sont destinees a ecrire du code safe.
    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. Problème de migration d'application
    Par UVCR dans le forum XMLRAD
    Réponses: 5
    Dernier message: 04/10/2005, 10h45
  2. Réponses: 5
    Dernier message: 24/09/2005, 20h31
  3. Problème d'installation d'application ".msi"
    Par maddog2032 dans le forum Windows Serveur
    Réponses: 4
    Dernier message: 16/09/2005, 11h31
  4. Réponses: 1
    Dernier message: 03/05/2005, 09h12
  5. [Thread][socket]Problème de fermeture d'un thread
    Par meda dans le forum Concurrence et multi-thread
    Réponses: 4
    Dernier message: 04/11/2004, 01h03

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