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 :

Problème avec Thread.sleep() dans JavaFX


Sujet :

JavaFX

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2018
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2018
    Messages : 31
    Points : 33
    Points
    33
    Par défaut Problème avec Thread.sleep() dans JavaFX
    Bonjour tout le monde,

    Je suis entrain de réaliser une mini-application du jeu de la bataille, et je bloque alors l'affiche des cartes.

    J'aimerai faire en sorte que toute les 1 ou 2 secondes les cartes se mette à jour pour laissez le tempsà notre d'apercevoir les changements et l'avancement de la partie.

    Seulement voila , j'ai tenté d'utiliser une Thread.sleep() mais je me retrouve avec quelque de très contre intuitif:
    - dans mon code j'ai un débugger qui m'affiche l'etat de la partie, et il s'affiche bien toute les 2 secondes
    - mais dans le même try catch avec le Thread, j'ai une instruction devant effecteur le mise à jour des cartes; et voila le plus bizarre, les images ne s'actualise pas durant le temps de mes delay, elle s'actualise seulemnt une fois à la fin de ma boucle sur le try catch.

    Voila mon code de la bataille:
    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
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
     
    package sample;
     
    import java.awt.image.AreaAveragingScaleFilter;
    import java.util.ArrayList;
     
    /**
     * War card game entity
     */
    public class War {
     
        /**
         * Player1
         */
        private Player player1;
        /**
         * Player2
         */
        private Player player2;
     
        /**
         * Carpet
         */
        private Carpet carpet;
        /**
         * Card box
         */
        private CardBox cardBox;
     
        protected Controller controller;
     
     
        /**
         * War card game constructor
         * @param controller
         */
        public War(Controller controller, Player player1, Player player2) {
            this.player1 = player1;
            this.player2 = player2;
            this.carpet = new Carpet();
            this.cardBox = new CardBox();
            this.controller = controller;
        }
     
        /**
         * Start the game
         */
        public ArrayList<String> nextTurn() {
     
            /////
            System.out.println("------ WAR CARD GAME ------\n");
            /////
     
            ArrayList<String> listInformations = new ArrayList<>();
     
            // Check there are all the cards in the card box
            this.cardBox.init();
     
            // Deal cards
            this.cardBox.shuffle();
            dealCards(player1, 3);
            dealCards(player2, 3);
     
     
            // Start game
            int numberTurn = 1;
     
            do {
                // Shuffle decks every 5 turns to avoid infinity loop
                if (numberTurn % 5 == 0) {
                    this.player1.shuffleDeck();
                    this.player2.shuffleDeck();
     
                    System.out.println("Decks shuffled\n");
                }
                // Players decks
                this.player1.showHand();
                this.player2.showHand();
                // Players reveal their card
                listInformations.add(player1PlayedCardPath());
                listInformations.add(player2PlayedCardPath());
     
                this.carpet.revealCard(player1.play());
                this.carpet.revealCard(player2.play());
                // See game
                this.carpet.display();
                // Result
                switch (this.carpet.compareCards()) {
                    case DRAW:
                        System.out.println("Draw\n");
                        break;
     
                    case PLAYER1_WIN:
                        this.player1.winTurn(carpet.takeAllCards());
                        break;
     
                    case PLAYER2_WIN:
                        this.player2.winTurn(carpet.takeAllCards());
                        break;
                }
                numberTurn ++;
     
            } while (this.player1.numberOfCards() != 0 && this.player2.numberOfCards() != 0);
     
            return listInformations;
        }
     
        /**
         * Deal cards to a player
         * @param player a player
         * @param nbCards a number of cards
         */
        private void dealCards(Player player, int nbCards) {
            for (int i = 0; i < nbCards; i++) {
                player.pickRandomCard(this.cardBox);
            }
        }
     
        public String player1PlayedCardPath() {
            int value = this.player1.getNextCard().getCardValue();
            String suit = this.player1.getNextCard().getCardSuit();
     
            return "imgCard/"+value+suit+".png";
        }
     
        public String player2PlayedCardPath() {
            int value = this.player2.getNextCard().getCardValue();
            String suit = this.player2.getNextCard().getCardSuit();
     
            return "imgCard/"+value+suit+".png";
        }
     
    }

    Ainsi que du Controller:
    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
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
     
    package sample;
     
    import javafx.fxml.FXML;
    import javafx.fxml.Initializable;
    import javafx.scene.control.Button;
    import javafx.scene.control.Label;
    import javafx.scene.image.Image;
    import javafx.scene.image.ImageView;
    import javafx.scene.layout.AnchorPane;
     
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.net.URL;
    import java.util.ArrayList;
    import java.util.ResourceBundle;
     
     
    public class Controller extends Thread implements Initializable {
     
        @FXML
        private ImageView deckPlayer1;
        @FXML
        private ImageView deckPlayer2;
     
        @FXML
        private ImageView playedCardPlayer1;
        @FXML
        private ImageView playedCardPlayer2;
     
        @FXML
        private AnchorPane window;
        @FXML
        private AnchorPane gameFrame;
     
        @FXML
        private Label namePlayer1;
        @FXML
        private Label namePlayer2;
     
        @FXML
        private Label nbCardPlayer1;
        @FXML
        private Label nbCardPlayer2;
     
        @FXML
        private Label stateGamePlayer1;
        @FXML
        private Label stateGamePlayer2;
     
        @FXML
        private Button button;
     
        private Player player1 = new Player("Thomas");
        private Player player2 = new Player("Théo");
     
        private War war;
     
     
        @Override
        public void initialize(URL url, ResourceBundle resourceBundle) {
            initDeckImage();
            initPlayerLabel();
            button.setText("Jouez !");
            this.war = new War(this, this.player1, this.player2);
        }
     
        @FXML
        public void start() {
            button.setVisible(false);
            this.game();
        }
     
        public void game()  {
            Thread thread = new Thread();
            for (int i = 0; i < 3; i++) {
                try {
                    updateView(this.war.nextTurn());
                    thread.sleep(2000);
                }
                catch (Exception e) {}
            }
        }
     
        public void updateView(ArrayList<String> infos) {
            setPlayedCardPlayer1(infos.get(0));
            setPlayedCardPlayer2(infos.get(1));
        }
     
        private void initDeckImage() {
            try {
                FileInputStream input = new FileInputStream("imgCard/red_back.png");
                Image image = new Image(input);
     
                deckPlayer1.setImage(image);
                deckPlayer2.setImage(image);
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
     
        private void initPlayerLabel() {
            namePlayer1.setText(player1.getName());
            namePlayer2.setText(player2.getName());
            nbCardPlayer1.setText("26");
            nbCardPlayer2.setText("26");
            stateGamePlayer1.setText("");
            stateGamePlayer2.setText("");
        }
     
        public void setPlayedCardPlayer1(String imgPath) {
                Image image = new Image("file:" + imgPath);
                playedCardPlayer1.setImage(image);
        }
     
        public void setPlayedCardPlayer2(String imgPath) {
            Image image = new Image("file:" + imgPath);
            playedCardPlayer2.setImage(image);
        }
    }
    Cela fait maintenant plusieurs heures que je n'arrive à rien, si vous pouviez m'aider.

    Merci bien.

  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 855
    Points
    22 855
    Billets dans le blog
    51
    Par défaut
    La réponse est simple, on n'utilise pas Thread.sleep() c'est mal (en JavaFX comme en Swing) sauf si on sait vraiment ce qu'on fait.

    Ici tu sembles avoir étendu la classe Thread mais en fait tu n'a jamais démarre ce nouveau thread donc en fait il semble qu'en fait tu soit en train de bloquer le JavaFX Animation Thread, ce qui est MAL. Et même si tu avais démarré ton thread tu aurais du interagir avec le contenu de ta scène a grands coups de Platform.invokeLater().

    Si tu veux faire une boucle de ce genre en JavaFX, tu peux utiliser AnimationTimer, par exemple qui est plutôt bien adapté aux jeux.

    Les autres manieres de lancer des taches sont via TimeLine ou Transition pour les animations graphiques et le couple Service/Task pour tout ce qui est tache de fond.
    L'utilisation d'un Thread externe est toujours possible mais il faut prendre des précaution et être bien sur de ce qu'on fait.
    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
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2018
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2018
    Messages : 31
    Points : 33
    Points
    33
    Par défaut
    Merci, du coup, j'ai modifier mon code comme suit:

    Controller.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
    18
     
    @FXML
        public void start() {
            button.setVisible(false);
            this.game();
        }
     
        public void game()  {
            timer = new AnimationTimer() {
                @Override
                public void handle(long l) {
                    updateView(war.nextTurn());
                }
     
            };
     
            timer.start();
        }
    Et les animations fonctionne parfaitement.

    Je n'arrive juste pas à trouver comment mettre un delay entre les animation (elle s'enchainent à la vitesse de l'éclair).

    Vous sauriez la commande?

  4. #4
    Membre éclairé

    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    453
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 453
    Points : 883
    Points
    883
    Billets dans le blog
    5
    Par défaut
    Il est très recommandé de ne jamais utiliser les threads.

    Il est préférable d'utiliser l'interface Runnable et le framework excecutor.

    Tu trouvera des informations ici:
    https://jmdoudoux.developpez.com/cou...r.php#executor

    Dans le cas de JavaFX, le framework executor a une surcouche, Task et Service.

    Ce tutoriel est d'ailleurs très bien fait:
    https://fabrice-bouye.developpez.com...thread-javafx/

  5. #5
    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 855
    Points
    22 855
    Billets dans le blog
    51
    Par défaut
    Le long passé en paramètre de la méthode handle() te permet de calculer le temps qu'il s'est écoulé depuis l'appel précédent de cette fonction et donc de calibrer tes animations en fonction de cette durée. En théorie AnimationTimer tourne à 60fps. Pour des animations plus classiques tu peux aussi passer par Timeline et les divers classes implémentant Transition
    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

  6. #6
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2018
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2018
    Messages : 31
    Points : 33
    Points
    33
    Par défaut
    Merci beaucoup à tous, mon problème est règlé.

    Voila le code permetttant un delay dans un AnimationTimer pour ce qui auront le même problème;

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
     AnimationTimer timer = new AnimationTimer() {
                private long lastUpdate = 0;
                @Override
                public void handle(long now) {
                    if (now - lastUpdate >= 1000_000_000) { // delay de 1000 ms
                        updateView(war.nextTurn());
                        lastUpdate = now;
                    }
                }
            };
            timer.start();

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

Discussions similaires

  1. Problème avec thread.sleep
    Par e.londres dans le forum Android
    Réponses: 3
    Dernier message: 02/09/2011, 16h19
  2. Problème avec XML.Clear dans un TXMLDocument
    Par Tardiff Jean-François dans le forum Composants VCL
    Réponses: 2
    Dernier message: 04/01/2005, 11h45
  3. Problème avec un LIKE dans une procédure stockée
    Par Oluha dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 22/12/2004, 14h38
  4. [VB.NET] Problème avec un OptionButton dans Excel 2003
    Par alfprod dans le forum Windows Forms
    Réponses: 3
    Dernier message: 09/09/2004, 13h40
  5. [MFC] problème avec les insertions dans CComboBox
    Par Joeleclems dans le forum MFC
    Réponses: 12
    Dernier message: 11/06/2004, 15h31

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