Partage
  • Partager sur Facebook
  • Partager sur Twitter

Compteur sur une fenêtre tkinter

    8 août 2018 à 3:17:27

    Bonjour à tous,

    J'essaie de créer une fenêtre tkinter dans lequel s'affiche un compteur.

    Voilà mon code, qui ne fonctionne pas :

    import time
    from tkinter import *
    
    
    #definition de la fenetre
    compteur_max = 10
    compteur = 0
    
    #fenetre graphique
    ma_fenetre = Tk()
    ma_fenetre.title("Fenetre")
    
    #labels
    affichage_compteur = Label(ma_fenetre, text=str(compteur), font = ("Helvetica", 12))
    affichage_compteur.grid(row=1, column=1)
    
    #Boutons
    bouton_lancer = Button(ma_fenetre, text = "Commencer", command = lambda: lancer(ma_fenetre))
    bouton_lancer.grid(row=3, column=1)
    
    
    
    def lancer(ma_fenetre):
        global compteur
        global compteur_max
    
        while compteur <= compteur_max:
            #demarrage
            affichage_compteur.configure(text=str(compteur))
            print("\n","\n")
            print("compteur", compteur)
           
    
    
            compteur +=1
            time.sleep(1) 
    
    ma_fenetre.mainloop()



    Le "print" me permet de voir le compteur défiler sur le terminal d'où je lance le programme, mais en revanche l'affichage sur la fenêtre ne se met à jour qu'à la fin du comptage. Elle affiche "0" pendant 10 secondes, puis "10".

    Comment se fait-ce ? j'ai pourtant mis affichage_compteur.configure(text=str(compteur)) à l'intérieur de la boucle, donc je m'attendrais à ce que la fenêtre affiche le bon nombre à chaque itération.

    Et comment puis-je résoudre mon souci ?

    Merci d'avance ! :D

    -
    Edité par JBMSL 8 août 2018 à 3:18:38

    • Partager sur Facebook
    • Partager sur Twitter
    Anonyme
      8 août 2018 à 9:41:09

      Voici le code corrigé,

      import time
      from tkinter import *
      
      
      #definition de la fenetre
      compteur_max = 10
      compteur = 0
      
      #fenetre graphique
      ma_fenetre = Tk()
      ma_fenetre.title("Fenetre")
      
      #labels
      affichage_compteur = Label(ma_fenetre, text=str(compteur), font = ("Helvetica", 12))
      affichage_compteur.grid(row=1, column=1)
      
      #Boutons
      bouton_lancer = Button(ma_fenetre, text = "Commencer", command = lambda: lancer(ma_fenetre))
      bouton_lancer.grid(row=3, column=1)
      
      def lancer(ma_fenetre):
          global compteur
          while compteur <= compteur_max:
              affichage_compteur['text'] = str(compteur)
              compteur += 1
              ma_fenetre.update_idletasks()
              time.sleep(1)
      
      ma_fenetre.mainloop()
      

      Par contre certaines choses ne vont pas,

      • Il faut éviter le mot clé global qui fou la merde dans un code python, surtout pour un débutant
      • Éviter les boucles while, pourquoi pas une boucle for
      • Éviter sleep qui fou la merde avec tkinter
      • compteur_max est une constante, mieux vaut l'écrire en majuscule COMPTEUR_MAX
      • Éviter l'importation from tkinter import * et préférer import tkinter as tk pour éviter les conflits entre noms de variables

      Il faudra donc partir sur une base propre pour continuer ton projet, mais le code ci-dessus te permet de faire un code test pour vérifier que ça fonctionne...

      • Partager sur Facebook
      • Partager sur Twitter
        8 août 2018 à 11:24:55

        Merci de ta réponse. J'ai corrigé l'importation de tkinter.  Pour éviter de mettre un "global", est-ce que cette solution est la bonne ?

        import time
        import tkinter as tk
        
        
        #definition de la fenetre 
        COMPTEUR_MAX = 10
        compteur = 0
        
        #fenetre graphique
        ma_fenetre = tk.Tk()
        ma_fenetre.title("Fenetre")
        
        #labels
        affichage_compteur = tk.Label(ma_fenetre, text=str(compteur), font = ("Helvetica", 12))
        affichage_compteur.grid(row=1, column=1)
        
        #Boutons
        bouton_lancer = tk.Button(ma_fenetre, text = "Commencer", command = lambda: lancer(ma_fenetre, compteur))
        bouton_lancer.grid(row=3, column=1)
        
        
        
        def lancer(ma_fenetre, compteur_fenetre):
            while compteur_fenetre <= COMPTEUR_MAX:
                #demarrage
                affichage_compteur.configure(text=str(compteur_fenetre))
                print("\n","\n")
                print("compteur", compteur_fenetre)
                ma_fenetre.update_idletasks()
        
        
                compteur_fenetre +=1
                time.sleep(1)  
        
        ma_fenetre.mainloop()

        Sinon, quelques questions sur les autres points que tu as soulevés :

        - Tu dis que sleep fout la merde avec tkinter. Est-ce qu'il y a un autre moyen de faire une pause entre les incrémentations ? J'avais pensé à quelques boucles for imbriquées pour obliger l'ordinateur à mouliner un peu pour rien, mais ça me semble pas terrible (on utilise de la puissance de calcul pour rien, et surtout, ça nuit à la portabilité du programme, puisque la durée de la pause va dépendre du processeur de l'ordinateur.)

        - Tu m'as corrigé

        affichage_compteur.configure(text=str(compteur))


        en

        affichage_compteur['text'] = str(compteur)

        Apparemment, les deux fonctionnent. Est-ce que ta version est mieux, ou bien les deux sont-elles deux écritures différentes d'une seule commande ?

        - Y a-t-il une raison particulière pour laquelle il faut éviter les boucles while ? De façon générale, j'ai tendance à préférer utiliser while que for, j'ai l'impression de contrôler plus facilement ce qu'il y a dedans. (Par exemple, si je décide qu'un événement fait passer directement le compteur à 10, ou qu'il descend de 1...)


        Encore merci !

        -
        Edité par JBMSL 8 août 2018 à 11:31:25

        • Partager sur Facebook
        • Partager sur Twitter
          8 août 2018 à 12:08:07

          Une autre solution pour implémenter ton compteur (autre que celle que tu as corrigée et qui est plutôt bonne) c'est de créer une classe compteur avec une méthode "increment" par exemple, tu créer un objet compteur au départ et puis tu appelle la méthode "increment" pour augmenter la valeur du compteur. Cela te permet si tu as besoin de plusieurs compteurs, d'avoir un moyen relativement élégant de les gérer.
          • Partager sur Facebook
          • Partager sur Twitter
          Anonyme
            8 août 2018 à 12:17:34

            Tu dis que sleep fout la merde avec tkinter. Est-ce qu'il y a un autre moyen de faire une pause entre les incrémentations ?

            Oui, voir du côté de la méthode after

            J'avais pensé à quelques boucles for imbriquées pour obliger l'ordinateur à mouliner un peu pour rien, mais ça me semble pas terrible (on utilise de la puissance de calcul pour rien, et surtout, ça nuit à la portabilité du programme, puisque la durée de la pause va dépendre du processeur de l'ordinateur.)

            Ça n'est pas ce que je voulais dire, je voulais que tu incrémentes ton compteur avec la boucle for, de la même manière qu'avec while... Seulement en python, on préfère grandement la boucle for à while. On évite surtout des variables inutiles.

            for compteur in range(COMPTEUR_MAX+1):
                affichage_compteur['text'] = str(compteur)

            plus simple, non ?

            JBMSL a écrit:

            - Tu m'as corrigé

            affichage_compteur.configure(text=str(compteur))


            en

            affichage_compteur['text'] = str(compteur)

            Apparemment, les deux fonctionnent. Est-ce que ta version est mieux, ou bien les deux sont-elles deux écritures différentes d'une seule commande ?

            Pas même écriture, mais elles font la même chose, seulement tu avoueras que la mienne est moins verbeuse, non ? ;)

            Le code pourrait ressembler à cela avec after

            import time
            import tkinter as tk
            
            #definition de la fenetre
            COMPTEUR_MAX = 10
            
            def lancer():
                id = ma_fenetre.after(1000, lancer)
                compteur.set(compteur.get()+1)
                affichage_compteur['text'] = str(compteur.get())
                if compteur.get() >= COMPTEUR_MAX:
                    ma_fenetre.after_cancel(id)
            
            #fenetre graphique
            ma_fenetre = tk.Tk()
            ma_fenetre.title("Fenetre")
            
            compteur = tk.IntVar()
            
            #labels
            affichage_compteur = tk.Label(ma_fenetre, text='0', font=("Helvetica", 12))
            affichage_compteur.grid(row=1, column=1)
            
            #Boutons
            bouton_lancer = tk.Button(ma_fenetre, text="Commencer", command=lancer)
            bouton_lancer.grid(row=3, column=1)
            
            ma_fenetre.mainloop()
            

            La gestion de la temporisation est mieux gérée de cette manière.

            • Partager sur Facebook
            • Partager sur Twitter

            Compteur sur une fenêtre tkinter

            × 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