Partage
  • Partager sur Facebook
  • Partager sur Twitter

Cherche problème dans un code

Avec Python - Tkinter

Sujet résolu
    29 novembre 2021 à 20:30:33

    Bonjour ! 

    J'utilise python pour une des premieres fois. Je cherche à faire un compteur d'échec. Ce sont deux comptes à rebours qui alternent a chaque fois que quelqu'un clique sur la fenêtre. Mais quand je clique, ca ne marche pas … Pouvez-vous m'aider ? Voici mon code … 

    # Importer
    import tkinter
    from tkinter import *
    import time
    
    # Fenetre
    window = Tk()
    
    # Configuration
    window.geometry("600x300")
    window.minsize(600, 300)
    window.maxsize(600, 300)
    window.title("Chess Counter")
    window.config(bg='black')
    
    
    # Variables
    M1 = 5
    S1 = 0
    
    M2 = 5
    S2 = 0
    
    var = 2
    
    # Definitions des fonctions
    
    
    def decompte1():
        global M1
        global S1
        while var == 1:
            if S1 == 1:
                time.sleep(1)
                M1 = M1-1
                S1 = 59
                return M1, S1
            else:
                time.sleep(1)
                S1 = S1-1
                return M1, S1
        maj()
    
    
    def decompte2():
        global M2
        global S2
        while var == 2:
            if S2 == 1:
                time.sleep(1)
                M2 = M2-1
                S2 = 59
                return M2, S2
            else:
                time.sleep(1)
                S2 = S2-1
                return M2, S2
        maj()
    
    
    def variable(evt):
        global var
        if var == 2:
            var = 1
            decompte1()
        else:
            var = 2
            decompte2()
    
    
    def maj():
        Time1S.set(str(M1) + " : " + str(S1))
        Time2S.set(str(M2) + " : " + str(S2))
    
    
    # Bouton Switch
    
    window.bind("<Button-1>", variable)
    
    
    # Label
    Time1S = tkinter.StringVar(window, "5 : 0")
    Time1 = Label(textvariable=Time1S, bg='black', fg='orange', font=("Courrier", 60))
    Time1.pack(side=RIGHT, padx=50)
    
    Time2S = tkinter.StringVar(window, "5 : 0")
    Time2 = Label(textvariable=Time2S, bg='black', fg='orange', font=("Courrier", 60))
    Time2.pack(side=LEFT, padx=50)
    
    
    # MainLoop
    window.mainloop()
    

    What's wrong ? 

    Thanks. 

    H. POIROT

    -
    Edité par JéDesProblemes! 29 novembre 2021 à 20:32:14

    • Partager sur Facebook
    • Partager sur Twitter
      30 novembre 2021 à 10:51:53

      Bonjour

      au départ, var=2

      au 1er clic, on va dans decompte1() qui teste while var ==1

      donc on ne rentre jamais dans la boucle

      dans decompte2(), il manque global var

      Sinon, tu pourrais mettre un peu d'ordre là-dedans

      pas besoin de import tkinter, from tkinter import * suffit

      ensuite, les définitions de fonctions

      puis les variables

      puis la définition de la fenêtre et des labels ...


      après, on peut faire beaucoup plus simple (c'est pour le principe, à adapter pour avoir minutes et secondes) :

      # -*- coding:Utf-8 -*-
      from tkinter import *
      
      def maj(evt):
          global c,c1,c2
      
          if(c==1):
              c1 -=1
              Time1.config(text = str(c1))
          else:
              c2 -=1
              Time2.config(text = str(c2))
      
          c = 3-c
      
      c1, c2 =5.0, 5.0
      c=1
      
      window = Tk()
      window.geometry("600x300")
      window.minsize(600, 300)
      window.maxsize(600, 300)
      window.title("Chess Counter")
      window.config(bg='black')
      window.bind("<Button-1>", maj)
      
      Time1 = Label(text=str(c1), bg='black', fg='orange', font=("Courrier", 60))
      Time1.pack(side=RIGHT, padx=50)
      
      Time2 = Label(text=str(c2), bg='black', fg='orange', font=("Courrier", 60))
      Time2.pack(side=LEFT, padx=50)
      
      window.mainloop()
      



      -
      Edité par Phil_1857 30 novembre 2021 à 11:17:19

      • Partager sur Facebook
      • Partager sur Twitter
        30 novembre 2021 à 11:19:28

        Phil_1857 a écrit:

        au 1er clic, on va dans decompte1() qui teste while var ==1

        donc on ne rentre jamais dans la boucle

        Au premier clic, on entre dans variable, la condition var == 2 est vraie, donc on assigne 1 à var avant d'appeler decompte1: on entre dans le while... On en ressort via les return (inutiles) et on atteint jamais l'appel à maj et rien ne se passe.

        Pour le reste, c'est compliqué car on se retrouve à devoir expliquer les bases de la programmation. Ce qui peut être longuet d'autant qu'on ne sait pas trop par où commencer... et botter en touche en suggérant d'ouvrir un tuto.

        • Partager sur Facebook
        • Partager sur Twitter
          30 novembre 2021 à 11:28:05

          Bonjour.

          Je pensais au même principe qu'expose Phil_1857 pour la gestion entre les 2 joueurs.

          Reste plus qu'à automatiser le décompte du temps tant que l'événement ne se produit pas.

          • Partager sur Facebook
          • Partager sur Twitter

          PB68

            30 novembre 2021 à 11:49:54

            En fait, ca marche un peu mieux comme ça:

            (reste à régler le problème des valeurs initiales)

            # -*- coding:Utf-8 -*-
            from tkinter import *
            import time
            
            def decompte(evt):
                global M1,S1,var,M2,S2
            
                if var == 1:
                    if S1 == 1:
                        time.sleep(1)
                        M1 -= 1
                        S1 = 59
            
                    else:
                        time.sleep(1)
                        S1 -= 1
                elif var == 2:
                    if S2 == 1:
                        time.sleep(1)
                        M2 -= 1
                        S2 = 59
            
                    else:
                        time.sleep(1)
                        S2 -= 1
            
                Time1.config(text = str(M1) + " : " + str(S1))
                Time2.config(text = str(M2) + " : " + str(S2))
            
                var = 3-var
            
            M1,S1 = 5,0
            M2,S2 = 5,0
            var = 2
            
            window = Tk()
            window.geometry("600x300")
            window.minsize(600, 300)
            window.maxsize(600, 300)
            window.title("Chess Counter")
            window.config(bg='black')
            window.bind("<Button-1>", decompte)
            
            Time1 = Label(text=str(M1) + " : " + str(S1), bg='black', fg='orange', font=("Courrier", 60))
            Time1.pack(side=RIGHT, padx=50)
            
            Time2 = Label(text=str(M2) + " : " + str(S2), bg='black', fg='orange', font=("Courrier", 60))
            Time2.pack(side=LEFT, padx=50)
            
            window.mainloop()
            



            -
            Edité par Phil_1857 30 novembre 2021 à 11:54:39

            • Partager sur Facebook
            • Partager sur Twitter
              30 novembre 2021 à 12:02:34

              Phil_1857 a écrit:

              En fait, ca marche un peu mieux comme ça:

              Si ça doit décompter le temps mis par chaque joueur d'une partie d'échec, ce code ne décompte que les clics de souris... quand il n'attend pas dans le time.sleep (à éviter avec tkinter).

              • Partager sur Facebook
              • Partager sur Twitter
                30 novembre 2021 à 12:14:22

                Apparemment, d'après le code initial du PO, l'affichage doit changer à chaque clic, non ?

                Ah non, je viens de relire, le décompte doit être continu et "changer de coté" à chaque clic ...

                Mais bon, je lui ai déjà simplifié son code (une fonction suffit) ...

                Attendons son retour pour confirmer tout ça ...

                • Partager sur Facebook
                • Partager sur Twitter
                Anonyme
                  30 novembre 2021 à 13:16:05

                  Un bout de code utile :

                  >>> import time
                  >>> time.strftime("%M:%S", time.gmtime(300))
                  '05:00'


                  Un exemple de code :

                  # Importer
                  from tkinter import *
                  import time
                   
                  # Fenetre
                  window = Tk()
                   
                  # Configuration
                  window.geometry("600x300")
                  window.minsize(600, 300)
                  window.maxsize(600, 300)
                  window.title("Chess Counter")
                  window.config(bg='black')
                  
                  # Variable
                  var = 0
                  
                  def decompte(timer):
                      timer.count -= 1
                      timer.svar.set(time.strftime('%M:%S', time.gmtime(timer.count)))
                      if not timer.count:
                          return
                      if var == 1:
                          window.after(1000,decompte,timer1)
                      else:
                          window.after(1000,decompte,timer2)
                  
                  def startandpause(evt):
                      global var
                      if not var:
                          var = 1
                          window.after(1000,decompte,timer1)
                      else:
                          var = 3-var
                          
                   
                  # Bouton Switch 
                  window.bind("<Button-1>", startandpause)
                   
                  # Label
                  Time1S = StringVar(window, "--:--")
                  Time1 = Label(textvariable=Time1S, bg='black', fg='orange', font=("Courrier", 60))
                  Time1.pack(side=RIGHT)
                  
                  Time2S = StringVar(window, "--:--")
                  Time2 = Label(textvariable=Time2S, bg='black', fg='orange', font=("Courrier", 60))
                  Time2.pack(side=LEFT)
                  
                  # class Timer contenant le StringVar à mettre à jour et le compteur en seconde
                  class Timer:
                      def __init__(self,v,t):
                          self.svar = v
                          self.count = t
                  
                  # Instances de classe
                  timer1 = Timer(Time1S, 300)
                  timer2 = Timer(Time2S, 300)
                  
                  # MainLoop
                  window.mainloop()
                  

                  Par contre je ne comprends pas pourquoi c'est si imprécis... Jusqu'à 3 secondes d'écart avec la réalité au bout de 5 minutes.

                  -
                  Edité par Anonyme 30 novembre 2021 à 13:21:50

                  • Partager sur Facebook
                  • Partager sur Twitter
                    30 novembre 2021 à 14:16:55

                    Ah pas mal l'utilisation de la classe

                    J'étais en train d'essayer de mon coté d'arrêter le décompte d'un coté pour le poursuivre de l'autre

                    Là ca marche bien sans faire une "usine à gaz" ...

                    -
                    Edité par Phil_1857 30 novembre 2021 à 14:18:33

                    • Partager sur Facebook
                    • Partager sur Twitter
                      30 novembre 2021 à 17:00:47

                      Phil_1857 a écrit:

                      Ah pas mal l'utilisation de la classe

                      J'étais en train d'essayer de mon coté d'arrêter le décompte d'un coté pour le poursuivre de l'autre

                      Là ca marche bien sans faire une "usine à gaz" ...

                      -
                      Edité par Phil_1857 il y a environ 1 heure


                      Ça se fait assez facilement sans classe. Le problème est la gestion du temps qui est imprécise avec "time.after()" qui s’exécutera que lorsque ce sera possible.

                      from tkinter import *
                      import time
                      
                      
                      # Variables globales
                      Temps_Jeu_Min = 5
                      
                      T1 = Temps_Jeu_Min * 60     # Temps en s pour J1
                      T2 = Temps_Jeu_Min * 60     # Temps en s pour J2
                      
                      J1 = False
                      
                      
                      # Fonctions
                      
                      def Compte_A_Rebours():
                          global J1, T1, T2
                      
                      
                          if J1 == True:
                              T1 -= 1
                              TxtVarJ1.set(time.strftime('%M:%S', time.gmtime(T1)))
                      
                          else:
                              T2 -= 1
                              TxtVarJ2.set(time.strftime('%M:%S', time.gmtime(T2)))
                      
                          window.after(1000, Compte_A_Rebours)
                      
                      
                      def maj(e):
                          global J1
                          if J1 == False:
                              J1 = True
                              Compte_A_Rebours()
                      
                          else:
                              J1 = False
                              Compte_A_Rebours()
                      
                      
                      # Fenêtre
                      window = Tk()
                      window.geometry("600x300")
                      window.resizable(0, 0)
                      window.title("Chess Counter")
                      window.config(bg='black')
                      
                      
                      # Widgets
                      TxtVarJ1 = StringVar(window,
                                           time.strftime('%M:%S', time.gmtime(Temps_Jeu_Min * 60))
                                           )
                      Lbl_J1 = Label(textvariable=TxtVarJ1,
                                     bg='black',
                                     fg='orange',
                                     font=("Courrier", 60)
                                     )
                      Lbl_J1.pack(side=RIGHT, padx=50)
                      
                      TxtVarJ2 = StringVar(window,
                                           time.strftime('%M:%S', time.gmtime(Temps_Jeu_Min * 60))
                                           )
                      Lbl_J2 = Label(textvariable=TxtVarJ2,
                                     bg='black',
                                     fg='orange',
                                     font=("Courrier", 60)
                                     )
                      Lbl_J2.pack(side=LEFT, padx=50)
                      
                      
                      # Gestion des événements
                      window.bind("<Button-1>", maj)
                      
                      
                      window.mainloop()

                      Avec pyQt5, il y a un vrai Timer qui permettra cette gestion du temps (un tuto, ici).

                      -
                      Edité par PB68 30 novembre 2021 à 17:01:44

                      • Partager sur Facebook
                      • Partager sur Twitter

                      PB68

                      Anonyme
                        30 novembre 2021 à 17:38:54

                        PB68 a écrit:

                        Ça se fait assez facilement sans classe. Le problème est la gestion du temps qui est imprécise avec "time.after()" qui s’exécutera que lorsque ce sera possible.

                        Je me demande si ça ne vient pas plutôt de tkinter tout court ? Car j'ai essayé avec un thread et time.sleep() et c'est pas mieux. Par contre je n'ai pas pensé à mettre sur un autre thread spécifique la MAJ de la StringVar uniquement... Va falloir que je me plonge dans PyQt un jour... lol
                        • Partager sur Facebook
                        • Partager sur Twitter
                          30 novembre 2021 à 19:19:15

                          J'ai comme l'impression que je me suis lancé dans trop dur pour un premier projet … :p Merci beaucoup à tous ! Je vais essayer de comprendre tout vos codes pour m'inspirer … Comment puis-je faire pour apprendre Python ?  Y a t-il un site qui donne des cours ? 

                          Merci a tous. 

                          H.

                          • Partager sur Facebook
                          • Partager sur Twitter
                          Anonyme
                            30 novembre 2021 à 19:39:05

                            La référence pour débutant : https://inforef.be/swi/download/apprendre_python3_5.pdf
                            • Partager sur Facebook
                            • Partager sur Twitter

                            Cherche problème dans un code

                            × 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