Partage
  • Partager sur Facebook
  • Partager sur Twitter

afficher dans un TextView un nombre qui varie

Sujet résolu
    27 novembre 2018 à 15:29:01

    bonjour,

    étant un gros, mais vraiment gros débutant en programmation et n'ayant eu que des cours de C à l'école je viens vers vous afin d'avoir un peu d'aide.

    Mon problème est le suivant. Je souhaiterais afficher dans des textviews des nombres qui varient en fonction du temps.

    (ex : le 1er textview va compter de 500 à 1000 et le 2eme de 1200 à 1500).

    pour cela j'ai essayé de passer par un onClickListener()

    et mon but était que je clic sur un bouton ou sur l'écran pour lancer une boucle "for"

    or mon textview ne retourne que la dernière valeur traité par la boucle "for" au lieu de me retourner toutes les valeurs.

    je suis désolé de ma maladresse sur les termes employés et de mon manque de clarté mais je ne sais pas comment être plus clair...

    en espérant que vous compreniez.

    voici le code XML :

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/v"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#000000"
        tools:context=".MainActivity">
    
        <ImageView
            android:id="@+id/FLI"
            android:layout_width="236dp"
            android:layout_height="208dp"
            android:contentDescription="@string/FLI"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.033"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.475"
            app:srcCompat="@drawable/fli_vide" />
    
        <TextView
            android:id="@+id/compteur"
            android:layout_width="91dp"
            android:layout_height="88dp"
            android:text="@string/RAA"
            android:textColor="#ffffff"
            android:textSize="30dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.918"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.461" />
    
        <TextView
            android:id="@+id/sling"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Sling 1200 kg"
            android:textColor="#ffffff"
            android:textSize="30dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.771"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.981" />
    
        <TextView
            android:id="@+id/hook"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/hook_n_open"
            android:textColor="#ffffff"
            android:textSize="30dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.347"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.981" />
    
        <ImageView
            android:id="@+id/flip"
            android:layout_width="50dp"
            android:layout_height="193dp"
            android:adjustViewBounds="false"
            android:contentDescription="@string/FLECHE"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.118"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.444"
            app:srcCompat="@drawable/fleche2" />
    
        <ImageView
            android:id="@+id/imageView"
            android:layout_width="368dp"
            android:layout_height="281dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:layout_marginEnd="8dp"
            android:layout_marginBottom="8dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.19"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.096"
            app:srcCompat="@drawable/flip" />
        
    
    </android.support.constraint.ConstraintLayout>
    

    et le code JAVA :

    package com.example.etzic.fli_final_v10;
    
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.view.View;
    import android.widget.TextView;
    
    public class MainActivity extends AppCompatActivity {
    
        private TextView compteurs;
        private TextView sling;
        private View v;
        private int clicks = 500;
        private int clicks2 = 1200;
    
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            this.compteurs = findViewById(R.id.compteur);
            this.sling = findViewById(R.id.sling);
            this.v = findViewById(R.id.v);
    
    
                v.setOnClickListener(new View.OnClickListener() {
    
                    @Override
                    public void onClick(View v) {
    
    
    
    
                        for (int a = 1; a < 10; a++) {
                            sling.setText("Sling " + a + " kg");     // cette commande s'exécute qu'à la fin de la boucle
                                                                    //sling retourne donc 9
                            compteurs.setText("RA\n" + clicks + " ft"); // idem
                            clicks++;
                            clicks2 = clicks2 + 5; // de base sert pour sling mais sling retourne a pour le débogage
    
    
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();       // du coup la tempo dure 1 sec * 10sec ...
                            }
    
    
                        }
    
    
                    }
    
    
                });
            }
    
        }
    
    

    merci pour votre aide

    Vincent

    • Partager sur Facebook
    • Partager sur Twitter
      27 novembre 2018 à 17:56:22

      Salut, T'es certain que ça ne s'exécute qu'une fois ? En mettant un breakpoint sur ton sling.setText ça donne quoi ?

      • Partager sur Facebook
      • Partager sur Twitter
        28 novembre 2018 à 9:28:27

        salut, merci de ta réponse ;)

        oui certain... au niveau de l'affichage sur mon appareil il ne se passe rien avant 8 seconde et m'affiche 9...

        Breakpoint ? tu l'intègre comment dans ton code ? 

        • Partager sur Facebook
        • Partager sur Twitter
          28 novembre 2018 à 10:40:29

          Il ne faut pas faire confiance à l'affichage. Il se passe peut-être des choses qui sont trop rapides pour que tu puisses le voir. Typiquement, tu fais une boucle de 1 à 10. Dans cette boucle tu as un setText et un thread.sleep. A l'affichage tu vois que la dernière valeur et tu penses que tu rentres qu'une fois dans ta boucle. Je vois deux problèmes à ta théorie : 

          - Si t'arrives à 9 c'est bien qu'il y a eu les autres itérations qui ont incrémenté ta variable, donc ta boucle a bien été parcouru plusieurs fois.

          - Si tu dois attendre 8s c'est bien que ton thread.sleep s'est exécuté plusieurs fois. Sinon, tu n'aurais attendu qu'une seconde. Donc ta boucle a bien été parcouru plusieurs fois.

          A moins que tu fasses un break ou un return il n'y a aucun raison qu'une boucle for s'arrête avant la fin. Donc pars du principe que la boucle for se comporte normalement, et que le problème vient du code que tu as mis.

          Pour mettre un breakpoint, clique à gauche des numéros de lignes dans ton IDE. C'est le meilleur moyen de debugger. Pour le supprimer, tu recliques sur le point rouge qui est apparu.

          Le seul truc "bizarre" dans ton code c'est le Thread.sleep(1000). Pose toi la question : C'est quoi Thread ? C'est quoi sleep ? Si je regarde la doc je peux lire :

          Thread.sleep causes the current thread to suspend execution for a specified period. 

          Donc, le current thread c'est lequel ? C'est le thread principal. La mise à jour du textView se fait sur quel Thread ? Le Thread principal. Donc, en mettant en pause le thread principal tu met en pause la mise à jour du TextView. C'est pour ça que rien ne s'affiche. Une fois que tous les Thread.sleep sont passés, l'affichage peut enfin être modifié. Mettre à jour un TextView ça va vite donc tu ne vois que la dernière valeur d'affichée (Je parie que si tu enlèves le Thread.sleep ça fait la même chose, mais en plus rapide).

          Conclusion : Thread.sleep n'est pas ce que tu souhaites utiliser. Je tape donc sur Google "Android delay execution" (parce que je ne connais pas Android). Et je tombe assez rapidement là dessus : https://stackoverflow.com/a/9166354/7468650

          Donc si je le modifie pour coller un peu à ton code, ça donnerait : 

          for (int a = 1; a < 10; a++) {
             final Handler handler = new Handler();
             handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                   sling.setText("Sling " + a + " kg"); 
                }
              }, 1000);
          }
                                                                          

          (J'ai pas testé, c'est au feeling. Mais comme tu sais comment debugger désormais, tu t'en sortiras ;)   )

          EDIT : en y réfléchissant un peu il faut peut être multiplier 1000 par A. Je pense que tu devrais utiliser un timer ce serait plus simple 

          -
          Edité par Geda 28 novembre 2018 à 13:11:57

          • Partager sur Facebook
          • Partager sur Twitter
            29 novembre 2018 à 9:30:34

            hello, tout d'abort merci pour ton aide ;) 

            mais aprés de nombreuses recherche j'ai enfin trouvé une solution ;)

            mon but était de faire varier un nombre indéfiniement ou très longtemps (d'où la boucle for) et de l'afficher dans un TextView.

            mais j'ai finalement décidé d'abandonner le "onClickListener" et utiliser un "run". (si d'ailleurs tu pouvais m'expliquer ce que fait le run (juste une exécution ?))

            j'ai mis le code ci dessous si par hasard d'autre personne on le même problème que moi ;)

            package com.example.etzic.fli_final_v10;
            import android.os.Bundle;
            import android.os.Handler;
            import android.support.v7.app.AppCompatActivity;
            import android.text.format.DateFormat;
            import android.view.View;
            import android.widget.TextView;
            
            import java.util.Calendar;
            import java.util.Random;
            
            public class MainActivity extends AppCompatActivity {
                private TextView compteurs;
                private TextView sling;
                private View v;
                private int clicks = 500;
                private int clicks2 = 1200;
            
                @Override
                protected void onCreate(Bundle savedInstanceState) {
                    super.onCreate(savedInstanceState);
                    setContentView(R.layout.activity_main);
            
            
            
                    Thread thread = new Thread() {
            
                        @Override
                        public void run() {
                            try {
                                while (true) {
                                    Thread.sleep(125);          // rafraichisssment tout les 500 ms !
                                    runOnUiThread(new Runnable() {
            
                                        @Override
                                        public void run() {
            
                                            TextView compteurs = findViewById(R.id.compteur);
                                            TextView sling = findViewById(R.id.sling);
            
            
                                            Random alea1 = new Random();
                                            int min1 = 500;
                                            int max1 = 600;
                                            int valeur1 = min1 +alea1.nextInt(max1-min1);
            
                                            Random alea2 = new Random();
                                            int min2 = 1200;
                                            int max2 = 1350;
                                            int valeur2 = min2 +alea1.nextInt(max2-min2);
            
                                            compteurs.setText("sling " + valeur1 +"kg");
            
            
                                            sling.setText("RA\n"+ valeur2+" ft");
                                        }
                                    });
                                }
                            } catch (InterruptedException e) {
                            }
                        }
                    };
            
                    thread.start();
                }
            }

            j'en ai déduit que le runOnUiThread force l'exécution du thread donc le rafraichissement ! 

            et peux tu me dire ce que fait le "thread.start();" concrétement ?

            merci de ton aide ;)


            Vincent 

            -
            Edité par VincentKirchhofer 29 novembre 2018 à 9:33:57

            • Partager sur Facebook
            • Partager sur Twitter
              29 novembre 2018 à 11:22:27

              Comme je disais, je ne connais pas Android. CEPENDANT, ça me semble suffisamment clair pour que je m'évite de regarder la doc.

              Ton application s'exécute sur plusieurs Thread. Le Thread principal sur lequel l'UI est rafraîchie  et un ou plusieurs thread sur lesquels sont exécutés les tâches lourdes afin de ne pas bloquer le thread principal (comme des téléchargements ou une boucle qui compte de 0 à 100000000).

              Ce que tu faisais avant : tu lançais Thread.sleep sur le thread principal, ce qui avait pour effet de bloquer l'UI.

              Ce que tu fais maintenant : tu créés un nouveau thread dans lequel tu fais un sleep. A la fin de ce sleep, tu dis au thread principal (runOnUiThread) de faire des modifs. runOnUiThread ne force pas l'exécution du thread (tu n'en as pas qu'un). Il indique juste que tel bout de code doit être exécuté sur le thread principal.

              C'est assez majeur comme concept, faudrait que tu le comprennes bien

              Thread.start c'est juste pour lancer ton nouveau thread, tout simplement. J'imagine que tu as une méthode stop si un jour tu veux l'arrêter.

              Je pense que niveau performance ce n'est pas terrible de faire findViewById dans ce bout de code. A mon avis c'est assez coûteux de trouver et de créer l'élément, tu ferais peut être mieux de le sortir de ta boucle.

              Un bout de Swift (que tu arriveras à lire je pense) pour mettre en évidence ce sujet de Thread :

              var x = 3
              
              // On lance un bout de code sur un autre thread
              DispatchQueue.global.async { 
                 x = 10
              }
              
              
              print(x)
              

              A ton avis, qu'est ce qui va sortir en console ? 

              Autre exercice : 

              var label = UILabel()
              label.text = "Je suis une TextView sur Android"
              
              DispatchQueue.global().async {
                 // On lance un bout de code sur le thread principal
                 // Equivalent à ton runOnUiThread
                 DispatchQueue.main.async { 
                    label.text = "Mon texte a changé"
                 }
              }
              
              sleep(10)
              print(label.text)

              Idem, qu'est ce qui va sortir dans la console ?

              Dernier exercice : 

              var x = 3
              
              DispatchQueue.global().async {
                  x = 15
                  // On lance un bout de code sur le thread principal
                  // Equivalent à ton runOnUiThread
                  DispatchQueue.main.async {
                      x = 10
                  }
              }
              
              sleep(5)
              print(x)
              




              • Partager sur Facebook
              • Partager sur Twitter
                29 novembre 2018 à 17:06:03

                j'aurais dit : 

                1) 3

                2) Mon texte a changé

                3) 10

                • Partager sur Facebook
                • Partager sur Twitter
                  30 novembre 2018 à 9:35:08

                  Les cas 2 et 3 sont assez similaires, je n'aurais pas dû les formuler comme ça. Dans les deux cas, le sleep fait que le thread principal se met en pause, donc l'exécution x = 10 (ou "Mon texte a changé") n'est pas exécuté non plus. A la fin du sleep, le print s'exécute avant la ligne dans le Dispatch (mais c'est pas évident...)

                  Pour le cas 3, le fait de faire un sleep() sur le thread principal n'impacte pas les autres threads. Donc l'exécution x = 15 est bien exécuté et c'est 15 qui s'affiche à la fin.

                  • Partager sur Facebook
                  • Partager sur Twitter

                  afficher dans un TextView un nombre qui varie

                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                  × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                  • Editeur
                  • Markdown