Partage
  • Partager sur Facebook
  • Partager sur Twitter

tkinter : récupérer une valeur

    9 août 2015 à 21:21:30

    Bonjour à tous !

    Je m'essaye actuellement le plus possible à tkinter, mais je n'arrive pas à récupérer une simple valeur depuis une Entry.

    Voici mon code :

    from tkinter import *
    
    class Joueur:
    
    	def __init__(self):
    		self.nom = "test"
    		main     = Tk()
    		askNom   = Entry(main)
    		askNom.grid(row = 0, column = 0)
    		buttonConfirm = Button(main, text="Valider", command=self.valider)
    		buttonConfirm.grid(row = 1, column = 0)
    		main.mainloop()
    		
    	def valider(self):
    		self.nom = askNom.get()
    		main.destroy()
    
    Joueur1 = Joueur()
    Joueur2 = Joueur()
    
    print(Joueur1.nom, Joueur2.nom)

    Le but est de créer une fenêtre pour chaque joueur. Cependant, j'obtiens lors de l’exécution une erreur comme quoi askNom n'est pas défini (alors que je le déclare avant d'utiliser la fonction). D'où vient mon erreur ? Comment pallier à ce problème ?

    Merci d'avance,

    BunshinKage

    • Partager sur Facebook
    • Partager sur Twitter
    Anonyme
      9 août 2015 à 21:25:17

      Tu ne peux pas avoir deux instances Tk, pour cela tu devras utiliser la classe Toplevel...

      et pour ton erreur, c'est self.askNom qu'il faut mettre !

      Tout ça c'est dans les tutos

      -
      Edité par Anonyme 9 août 2015 à 21:27:14

      • Partager sur Facebook
      • Partager sur Twitter
      Anonyme
        9 août 2015 à 21:50:10

        Je propose quand même une solution rapide, j'essaye de faire au plus simple pour que tu comprennes...

        from tkinter import *
        
        class Joueur:
        	
        	instance = 0
        	
        	def __init__(self, name):
        		
        		if Joueur.instance == 0:
        			self.tk = Tk()
        		else:
        			self.tk = Toplevel()
        
        		self.tk.title(name)
        
        		Joueur.instance += 1
        		
        joueur1 = Joueur("joueur1")
        joueur2 = Joueur("joueur2")
        
        joueur1.tk.mainloop()



        • Partager sur Facebook
        • Partager sur Twitter
          9 août 2015 à 22:05:21

          Je me suis intéressé à Toplevel, mais je ne vois pas bien ses avantages.

          Est-ce que c'est par convention parce que cela fait un code plus propre que l'on l'utilise ? (C'est pas une question troll hein, c'est une vraie question)

          Parce que du coup, j'ai réussi à goupiller un truc fonctionnel sans lui, qui est le résultat que j'attendais :

          from tkinter import *
          
          #main = Tk()
          
          class Joueur:
          
          	def __init__(self):
          		self.nom = "test"
          		#daughter = Toplevel(main)
          		self.daughter = Tk()
          		self.askNom   = Entry(self.daughter)
          		self.askNom.grid(row = 0, column = 0)
          		buttonConfirm = Button(self.daughter, text="Valider", command=self.valider)
          		buttonConfirm.grid(row = 1, column = 0)
          		self.daughter.mainloop()
          		
          	def valider(self):
          		self.nom = self.askNom.get()
          		self.daughter.destroy()
          
          Joueur1 = Joueur()
          Joueur2 = Joueur()
          
          print(Joueur1.nom, Joueur2.nom)



          • Partager sur Facebook
          • Partager sur Twitter
          Anonyme
            9 août 2015 à 22:17:10

            Pas plus d'une instance Tk, c'est une régle ! Pourquoi ? L'instance Tk représente la boucle événementielle (boucle infinie) permettant de gérer tous les événements liés à Tkinter.

            Tu te doutes bien, que si tu places deux boucles événementielles dans le même programme il risque d'y avoir des soucis avec blocage du programme lié aux boucles infinies.

            Bref tu peux tenter pour vérifier mes dires, je te laisse faire, le problème viendra tout seul !

            Une discussion pour confirmer...

            -
            Edité par Anonyme 9 août 2015 à 22:19:23

            • Partager sur Facebook
            • Partager sur Twitter
              9 août 2015 à 22:48:33

              Disons que je vois un peu ce que je fais comme ça :

              while 1:
              
                 try:
                    nombre = int(input("Rentrez un nombre"))
                    break
                 except:
                    print("Saisie non-valide")

              C'est-à-dire que je crée une boucle infinie, mais au final, je suis sûr et certain de l'arrêter.

              Donc, en théorie, si je fais ça à ma manière, ça fonctionnera mais ce sera dégueulasse d'un point de vue code, alors que comme tu m'as dit cela fait propre ? Bon, ben je vais faire à ta méthode alors ^^ 

              • Partager sur Facebook
              • Partager sur Twitter
              Anonyme
                9 août 2015 à 22:57:40

                Non ce n'est pas pareil, mais fait comme tu veux ! C'est pas comme si j'avais 10 ans de python derrière moi... Autant le découvrir par toi même, il y en a qui ont besoin de se planter et d'autres pas, c'est la vie.

                Rien à voir avec dégueulasse ou pas, là je parle de fonctionnement du code, tu n'en n'es qu'au début, mais quand tu l'auras rendu plus complexe, on en reparle ;)

                • Partager sur Facebook
                • Partager sur Twitter
                  10 août 2015 à 1:03:51

                  Non mais je veux bien te croire (c'est pour ça que je vais prendre ton exemple ^^), mais je ne comprends pas quelle est la différence en fait, c'est tout ^^
                  • Partager sur Facebook
                  • Partager sur Twitter
                    10 août 2015 à 5:51:42

                    BunshinKage a écrit:

                    Le but est de créer une fenêtre pour chaque joueur

                    Le problème avec l'existence de plusieurs instances de TK est que tu ne peux avoir qu'une boucle infinie à la fois. Dans ton exemple plus haut, où tu montres comment tu vois cette boucle infinie, et bien cette boucle-là c'est la boucle de laquelle des deux fenêtres ouvertes? Celle de joueur 1 ou de joueur 2? Mettons que ce soit celle de joueur 1. Alors le code n'a jamais l'occasion d'avancer pour créer la fenêtre pour joueur 2. C'est seulement quand on détruit l'instance de TK avec destroy qu'on peut continuer notre code. C'est pas vraiment ce qu'on veut. Essaie ce code. Tu n'aura pas l'opportunité de voir la deuxième fenêtre tant que la première n'aura pas été fermée.

                    from tkinter import *
                    

                    class Joueur:

                    def __init__(self):
                        self.main = Tk()
                        self.nom = Entry(self.main)
                        self.nom.grid(row = 0, column = 0)
                        self. button_confirm = Button(self.main, text="Valider", command=self.valider)
                        self. button_confirm.grid(row = 1, column = 0)
                        self.main.mainloop()
                         
                    def valider(self):
                        print(self.nom.get())
                    

                    Joueur1 = Joueur() Joueur2 = Joueur()

                    </pre>

                    Par contre avec ce code-ci, tu as deux nouvelles fenêtres en plus de la fenêtre principale qui s'ouvrent. L'utilisateur peut interagir avec celle qu'il veut. Elles répondent en même temp à l'utilisateur.

                    from tkinter import *
                    

                    class Joueur:

                    def __init__(self, app):
                        self.main = Toplevel(app)
                        self.nom = Entry(self.main)
                        self.nom.grid(row = 0, column = 0)
                        self. button_confirm = Button(self.main, text="Valider", command=self.valider)
                        self. button_confirm.grid(row = 1, column = 0)
                         
                    def valider(self):
                        print(self.nom.get())
                    

                    app = Tk() Joueur1 = Joueur(app) Joueur2 = Joueur(app) app.mainloop()

                    </pre> Finalement si le comportement désiré est de n'avoir qu'une seule fenêtre mais de voir tour à tour le formulaire pour rentrer le nom du joueur 1 puis du joueur 2, alors tu pourrais procéder comme ceci:
                    from tkinter import *
                    

                    class Names(Frame):

                    def __init__(self, app):
                        super().__init__(app)
                        self.joueur1 = Joueur(self)
                        self.joueur2 = Joueur(self)
                        self.joueur1.grid()
                    
                    def name_entered(self, joueur):
                        if joueur is self.joueur1:
                            self.joueur1.grid_forget()
                            self.joueur2.grid()
                        else:
                            self.joueur2.grid_forget()
                            self.main_game()
                    
                    def main_game(self):
                        Label(self, text="Joueur 1: {}".format(self.joueur1.nom.get())).grid()
                        Label(self, text="Joueur 2: {}".format(self.joueur2.nom.get())).grid()
                    

                    class Joueur(Frame):

                    def __init__(self, parent):
                        super().__init__(parent)
                        self.nom = StringVar()
                        self.nom_entry = Entry(self, textvariable=self.nom)
                        self.nom_entry.grid(row = 0, column = 0)
                        self. button_confirm = Button(self, text="Valider", command=self.valider)
                        self. button_confirm.grid(row = 1, column = 0)
                         
                    def valider(self):
                        self.master.name_entered(self)
                    

                    app = Tk() names_frame = Names(app) names_frame.grid() app.mainloop()

                    </pre>
                    • Partager sur Facebook
                    • Partager sur Twitter
                      10 août 2015 à 20:33:05

                      Dan737 a écrit:

                      BunshinKage a écrit:

                      Le but est de créer une fenêtre pour chaque joueur

                      Le problème avec l'existence de plusieurs instances de TK est que tu ne peux avoir qu'une boucle infinie à la fois.

                      Justement, je n'ai besoin que d'une boucle infinie à la fois, c'est pour ça que je ne comprends pas en quoi c'est gênant ^^

                      Dan737 a écrit:

                      C'est seulement quand on détruit l'instance de TK avec destroy qu'on peut continuer notre code. C'est pas vraiment ce qu'on veut.

                      Essaie ce code. Tu n'aura pas l'opportunité de voir la deuxième fenêtre tant que la première n'aura pas été fermée.

                      Je ne vois pas ce que tu veux dire. Dans le cas où je veux effectivement ne faire qu'une fenêtre à la fois, tu dis que ce n'est pas gênant de procéder comme je l'ai fait (ou alors j'ai mal interprété ^^ ).

                      Je veux dire, dans les deux cas, on a une fene^tre qui s'ouvre, on ferme, et on en ouvre une deuxième, non ?

                      Mais merci pour les codes :D

                      • Partager sur Facebook
                      • Partager sur Twitter

                      tkinter : récupérer une valeur

                      × 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