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

Tkinter Python Discussion :

Mauvaise réponse python


Sujet :

Tkinter Python

  1. #1
    Membre à l'essai
    Homme Profil pro
    magasinié
    Inscrit en
    Décembre 2018
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : magasinié

    Informations forums :
    Inscription : Décembre 2018
    Messages : 34
    Points : 21
    Points
    21
    Par défaut Mauvaise réponse python
    Bonjour,

    J'ai essayé de juste mettre en avant la partie qui ne marche pas.
    Quand je clique sur le bouton pour décaler à droite, mon programme ne le fait que 1 fois et je n'arrive pas à comprendre pourquoi :
    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
    from tkinter import *
    from math import *
     
     
    class Sphere(object):
        def __init__(self):
            self.fen = Tk()
            self.can = Canvas(self.fen, width=500, height=500, bg='white')
            self.can.pack()
            self.sphere()
            Button(self.fen, text='->', command=self.droite1).pack(side=LEFT)
            self.fen.mainloop()
     
        def sphere(self):
            self.x1 = 100
            self.y1 = 100
            self.astre1 = self.can.create_oval(self.x1, self.y1, self.x1 + 40, self.y1 + 40, fill='red')
     
        def bouge(self,h,g,x,y,astre):
            x += h
            y += g
            self.can.coords(astre, x, y, x + 40, y + 40)
     
        def droite1(self):
            self.bouge(10,0,self.x1,self.y1,self.astre1)
     
     
    a = Sphere()
    Quand je fais :
    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
    from tkinter import *
    from math import *
     
     
    class Sphere(object):
        def __init__(self):
            self.fen = Tk()
            self.can = Canvas(self.fen, width=500, height=500, bg='white')
            self.can.pack()
            self.sphere()
            Button(self.fen, text='->', command=self.droite1).pack(side=LEFT)
            self.fen.mainloop()
     
        def sphere(self):
            self.x1 = 100
            self.y1 = 100
            self.astre1 = self.can.create_oval(self.x1, self.y1, self.x1 + 40, self.y1 + 40, fill='red')
     
        def bouge(self,h,g):
            self.x1 += h
            self.y1 += g
            self.can.coords(self.astre1, self.x1, self.y1, self.x1 + 40, self.y1 + 40)
     
        def droite1(self):
            self.bouge(10,0)
     
     
    a = Sphere()
    Je n'ai aucune soucis..

    Merci
    Bonne soirée

  2. #2
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 873
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 873
    Points : 3 717
    Points
    3 717
    Par défaut
    Salut,

    C'est parce que dans le code 1 tu passes toujours les mêmes valeurs en paramètres :

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    def bouge(self, h, g, x, y, astre):
            x += h
            y += g
            self.can.coords(astre, x, y, x + 40, y + 40)
     
        def droite1(self):
            self.bouge(10, 0, self.x1, self.y1, self.astre1)

    A chaque exécution de cette ligne : self.bouge(10, 0, self.x1, self.y1, self.astre1) les paramètres ont toujours les mêmes valeurs, elles ne varient jamais (à chaque appel), en particulier les variables self.x1 et self.y1 ne changent pas...

    Alors que dans l'autre code ces deux variables changent :

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    def bouge(self, h, g):
            self.x1 += h
            self.y1 += g
            self.can.coords(self.astre1, self.x1, self.y1,
                            self.x1 + 40, self.y1 + 40)
     
        def droite1(self):
            self.bouge(10, 0)

    Le changement a lieu aux lignes 2 et 3...

    Dans le code 1, après le premier déplacement, la nouvelle position n'est pas enregistrée (dans les variables self.x1 et self.y1) du coup à chaque clique (après le premier) il reste au même endroit...

  3. #3
    Membre à l'essai
    Homme Profil pro
    magasinié
    Inscrit en
    Décembre 2018
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : magasinié

    Informations forums :
    Inscription : Décembre 2018
    Messages : 34
    Points : 21
    Points
    21
    Par défaut
    Bonjour,

    Merci, avec des tests j'avais l'impression que le soucis venaient des deux lignes même si je n'étais pas à 100% sur.

    Du coup ma grande question :
    Pourquoi les valeurs restent les mêmes ?
    Sur ma ligne : x += h
    x = self.x1 et h = 10
    Donc pourquoi self.x1 ne prend +10 qu'une seule fois ?

    C'est exactement le même code sauf que j'ai remplacé les self.x1 avec x.
    Je ne comprend vraiment pas...
    Merci

  4. #4
    Membre à l'essai
    Homme Profil pro
    magasinié
    Inscrit en
    Décembre 2018
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : magasinié

    Informations forums :
    Inscription : Décembre 2018
    Messages : 34
    Points : 21
    Points
    21
    Par défaut
    j'ai fais comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        def droite1(self):
            self.bouge(10, 0, self.x1, self.y1, self.astre1)
            self.x1 += 10
    je ne comprend quand même pas pourquoi j'ai besoin de le faire.

    n'équivaut pas à ?

    Du coup je dois rajouter cette ligne sur chaque fonction pour le mouvement et j'ai 10 lignes au lieu de seulement 1.

    merci

  5. #5
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Salut,

    Parce que dans le premier cas self.x et self.y ne sont jamais mis à jour avec les nouvelles valeurs.

  6. #6
    Membre à l'essai
    Homme Profil pro
    magasinié
    Inscrit en
    Décembre 2018
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : magasinié

    Informations forums :
    Inscription : Décembre 2018
    Messages : 34
    Points : 21
    Points
    21
    Par défaut
    Citation Envoyé par VinsS Voir le message
    Salut,

    Parce que dans le premier cas self.x et self.y ne sont jamais mis à jour avec les nouvelles valeurs.
    J'ai bien compris, je ne comprend pas le pourquoi vue que j'ai x += h
    donc pourquoi la ligne ne marche pas pour incrémenter ma variable self.x1 vue que x = self.x1

    Je dois me perdre tout seul...

    Du coup en gros mon x+= h ne change pas la valeur de self.x1 sur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    self.bouge(10, 0, self.x1, self.y1, self.astre1)
    Et je ne comprend pas pourquoi ^^


    Version final, pardon pour les Edits, j'ai ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        def bouge(self, x, y, astre):
            self.can.coords(astre, x, y, x + 40, y + 40)
     
        def droite1(self):
            self.x1 += 10
            self.bouge(self.x1, self.y1, self.astre1)
    J'aurais voulu faire comme c'était prévu à la base mais bon apparemment c'est pas possible et les variables h et g étaient donc inutile.

  7. #7
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Il n'y a pas de variable en Python. Python fait de l'étiquetage, il crée une instance d'entier (int) avec la valeur 10 par exemple et lui colle l'étiquette self.x. Ensuite lorsque tu fais self.x += 10 il crée une nouvelle instance d'entier avec la valeur 20 et lui colle l'étiquette self.x qu'il enlève de la première instance.

    Et quand tu fais x += h tu ne lui dis pas expressément d'attribuer à cette nouvelle valeur l'étiquette self.x mais seulement x. Donc, self.x reste collée à la première instance.

  8. #8
    Membre à l'essai
    Homme Profil pro
    magasinié
    Inscrit en
    Décembre 2018
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : magasinié

    Informations forums :
    Inscription : Décembre 2018
    Messages : 34
    Points : 21
    Points
    21
    Par défaut
    Oki merci pour l'explication

  9. #9
    Membre à l'essai
    Homme Profil pro
    magasinié
    Inscrit en
    Décembre 2018
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : magasinié

    Informations forums :
    Inscription : Décembre 2018
    Messages : 34
    Points : 21
    Points
    21
    Par défaut
    Dernière petite question, j'ai amélioré le programme pour mettre un bouton qui permet de bouger l'astre à l'endroit de mon clic.

    J'ai fais deux fonction et j'aimerais savoir si c'était faisable en 1 avec le .bind et le .coord.
    Et si il y a une solution pour le 'event' sans devoir mettre 'None'.

    Merci
    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
    from tkinter import *
    from math import *
     
     
    class Sphere(object):
        def __init__(self):
            self.fen = Tk()
            self.can = Canvas(self.fen, width=500, height=500, bg='white')
            self.can.pack()
            self.sphere()
            Button(self.fen, text='->', command=self.droite1).pack(side=LEFT)
            Button(self.fen, text='t', command=self.test).pack()
     
            self.fen.mainloop()
     
        def sphere(self):
            self.x1 = 100
            self.y1 = 100
            self.astre1 = self.can.create_oval(self.x1 - 20, self.y1 - 20, self.x1 + 20, self.y1 + 20, fill='red')
     
        def bouge(self, x, y, astre):
            self.can.coords(astre, x - 20, y - 20, x + 20, y + 20)
     
        def droite1(self):
            self.x1 += 10
            self.bouge(self.x1, self.y1, self.astre1)
     
        def test(self):
            self.can.bind("<Button-1>", self.bouge2)
     
        def bouge2(self, event=None):
            self.can.coords(self.astre1, event.x - 20, event.y - 20, event.x + 20, event.y + 20)
            self.x1 = event.x
            self.y1 = event.y
     
     
    a = Sphere()

  10. #10
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 873
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 873
    Points : 3 717
    Points
    3 717
    Par défaut
    Salut,
    Citation Envoyé par outiat Voir le message
    Du coup ma grande question :
    Oui en effet c'est une grande question, je ne suis qu'un débutant en Python mais on voit ça dans d'autres langages aussi alors le concept est bien connu, le principe doit être le même je pense...

    Cette question concerne les valeurs et les références...
    Dans le cas d'une fonction la question devient est-ce une valeur ou bien une référence qui est transmis en paramètre ?
    Dans le cas d'une affectation est-ce une valeur ou bien une référence qu'on affecte ?

    Citation Envoyé par outiat Voir le message
    Du coup ma grande question :
    Pourquoi les valeurs restent les mêmes ?
    Sur ma ligne : x += h
    x = self.x1 et h = 10
    Donc pourquoi self.x1 ne prend +10 qu'une seule fois ?

    C'est exactement le même code sauf que j'ai remplacé les self.x1 avec x.
    Quand tu fais x = self.x1 tu affectes à la variable x la valeur contenue dans la variable self.x1...

    Ici c'est bien une valeur qui a été affectée : la valeur contenue dans self.x1 a été affectée à x.

    C'est important de comprendre que c'est une valeur qui a été affectée (et non une référence) car la conséquence c'est que les variables x et self.x1 sont indépendantes l'une de l'autre bien qu’après l'affectation x = self.x1 elles contiennent toutes les deux la même valeur...

    Elles sont indépendantes l'une de l'autre cela signifie que si par la suite tu modifies l'une des deux cette modification n'affectera pas l'autre.

    Si par exemple tu fais x += 10 cela ajoutera 10 à x mais self.x1 ne sera pas affectée, elle reste inchangée.

    ---> Si c'était une référence qui était affectée il en irait autrement.

    Du coup la question qu'on peut se poser c'est comment savoir si c'est une valeur ou une référence qui est affectée ?
    Eh bien cela dépend du type de la variable : en général dans le cas des variables de type primitif/natif (comme les nombres entiers ou décimaux, les chaines de caractères, les booléens...) c'est la valeur qui est affectée et dans le cas des objets (comme les listes, les dictionnaires...) c'est la référence qui est affectée.





    Citation Envoyé par outiat Voir le message
    J'ai bien compris, je ne comprend pas le pourquoi vue que j'ai x += h
    donc pourquoi la ligne ne marche pas pour incrémenter ma variable self.x1 vue que x = self.x1

    Je dois me perdre tout seul...

    Du coup en gros mon x+= h ne change pas la valeur de self.x1 sur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    self.bouge(10, 0, self.x1, self.y1, self.astre1)
    Et je ne comprend pas pourquoi ^^
    La question ici est de savoir si une valeur ou bien une référence qui est transmis en paramètre ? C'est le même principe que pour l'affectation vu ci-dessus...

    Ici les variables self.x1 et self.y1 sont de type 'entier' c'est donc la valeur qu'ils contiennent qui est transmise en paramètre de la fonction self.bouge.

    Ainsi donc modifier x et y à l'intérieur de la fonction self.bouge n'affectera pas les variables self.x1 et self.y1.

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     def bouge(self,h,g,x,y,astre):
            x += h
            y += g
            self.can.coords(astre, x, y, x + 40, y + 40)

    Du coup petite parenthèse on peut se rendre compte que passer les paramètres x et y dans la fonction self.bouge ne sert à rien car tu n’utilises pas leur valeur.

    Bref, c'est un gros sujet et je t'ai peut-être embrouillé pour l'instant mais par la suite peut-être que cela deviendra plus clair.

    Tu pourrais voir comment cela se passe quand c'est une référence qui est transmise : l'exemple classique est de passer une liste en paramètre puis de modifier ce dernier et voir si la modification se répercute aussi sur la variable qui a été transmise...

  11. #11
    Membre à l'essai
    Homme Profil pro
    magasinié
    Inscrit en
    Décembre 2018
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : magasinié

    Informations forums :
    Inscription : Décembre 2018
    Messages : 34
    Points : 21
    Points
    21
    Par défaut
    Merci c'est très clair, je n'avais pas du tout pensé à ça ^^

    Au moins maintenant c'est clair !

  12. #12
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 873
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 873
    Points : 3 717
    Points
    3 717
    Par défaut
    Ben tant mieux si c'est clair...

    Je voulais quand même te dire que j'ai regardé vite fait comment on parle de ce sujet dans le langage Python et alors on tombe notamment sur les histoires d'objets mutables et immutables... D'ailleurs dernièrement j'avais vu ce sujet dans un fil récent dans lequel il y a une explication intéressante de wiztricks ici #10 ...




    Citation Envoyé par outiat Voir le message
    Dernière petite question, j'ai amélioré le programme pour mettre un bouton qui permet de bouger l'astre à l'endroit de mon clic.

    J'ai fais deux fonction et j'aimerais savoir si c'était faisable en 1 avec le .bind et le .coord.
    Je ne suis d'avoir compris ta question (peut-être pourrais-tu expliqué un peu plus ?) mais apparemment tu veux écrire ton code d'une manière plus concise et je me demandais pourquoi tu passais en paramètres les variables telles que self.astre1, self.x1, self.y1... ? Étant donné que ce sont des attributs, les méthodes y ont accès, non ?

    Exemple :
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        def bouge(self, x, y, astre):
            self.can.coords(astre, x - 20, y - 20, x + 20, y + 20)
     
        def droite1(self):
            self.x1 += 10
            self.bouge(self.x1, self.y1, self.astre1)

    Pourquoi ne pas juste écrire :
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        def bouge(self):        
            self.can.coords(self.astre1, self.x1 - 20, self.y1 - 20, self.x1 + 20, self.y1 + 20)        
     
        def droite1(self):
            self.x1 += 10
            self.bouge()

    Et puisque tu veux diminuer le nombre de fonction alors on pourrait même se contenter de la fonction droite1 :

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    def droite1(self):
       self.x1 += 10
       self.can.coords(self.astre1, self.x1 - 20, self.y1 - 20, self.x1 + 20, self.y1 + 20)

    C'est juste une idée...

  13. #13
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Citation Envoyé par outiat Voir le message
    Dernière petite question, j'ai amélioré le programme pour mettre un bouton qui permet de bouger l'astre à l'endroit de mon clic.
    Vous simplifieriez grandement votre code en utilisant move et moveto pour déplacer les objets et en récupérant l'encombrement via .bbox pour gérer les collisions.
    .moveto est une fonctionnalité que les développeurs ont omis d'intégrer et qui doit être ajoutée comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    class MyCanvas(Canvas):
        def moveto(self, *args):
            self.tk.call((self._w, 'moveto') + args)
    en attendant la version de Python qui...

    Citation Envoyé par outiat Voir le message
    Et si il y a une solution pour le 'event' sans devoir mettre 'None'.
    event = None sert à rendre la fonction utilisable comme callback (appelée par tkinter) avec ou sans event en paramètre.
    Mais si la fonction utilise event comme variable locale:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        def bouge2(self, event=None):
            self.can.coords(self.astre1, event.x - 20, event.y - 20, event.x + 20, event.y + 20)
            self.x1 = event.x
            self.y1 = event.y
    impossible de l'appeler sans event en paramètre.
    Dans ce cas, event est nécessaire et le =None ne sert à rien.

    Par ailleurs, je comprends que çà fasse "bien" d'utiliser les classes mais vous voyez bien que votre Sphere est bien plus qu'une sphère: c'est presque toute votre application.
    De plus, un objet ayant un état, il se réduit à l'identifiant retourné par .create_oval (la position se récupère via .coords ou .bbox) que vous pouvez remplacer par le tag/marque "sphere".

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

Discussions similaires

  1. mauvaise réponse de backend
    Par carber dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 0
    Dernier message: 29/10/2013, 10h39
  2. JMeter renvoie une mauvaise réponse
    Par chrime71 dans le forum Environnement de Développement Intégré (EDI)
    Réponses: 1
    Dernier message: 09/08/2012, 14h30
  3. Mauvaise réponse d'une requête avec mysql_fetch_row
    Par psychoBob dans le forum Requêtes
    Réponses: 14
    Dernier message: 20/06/2006, 12h26

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