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 :

Lier un évenement sur un widget dans une classe à une fonction dans la classe parente [Python 3.X]


Sujet :

Tkinter Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre régulier
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Janvier 2013
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2013
    Messages : 8
    Par défaut Lier un évenement sur un widget dans une classe à une fonction dans la classe parente
    Bonjour,

    Je ne sais même pas si l'intitulé est clair, débutant en python pas vraiment de base en poo, malgré mes recherches je n'arrive pas à transposer quelques lignes simples écrites moyennant une seule classe en un programme plus structuré qui fait appel à plusieurs classes. Mon problème est l'association d'un évènement <FocusOut> -par exemple- sur une des instances Entry à une fonction dans une classe parente.

    Le code que je n'arrive pas à faire fonctionner, dans cette version là (parmi plusieurs) j'ai une erreur que je crois comprendre, mais comment faire?
    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
    38
    39
    40
    41
    42
    43
    44
    45
     
    from tkinter import *
     
    # une fenêtre pour saisir une ligne comptable par exemple
    class MonApp(Tk):               
        def __init__(self):
            Tk.__init__(self)
            self.title('MonApplication')
            num1=Numericals(self)
     
    # un frame regroupe les montants à saisir et/ou pré-calculés 
    class Numericals(Frame):
        def __init__(self, parent):
            Frame.__init__(self, parent=None)
            self.pack(side=LEFT)
            vHT=FieldFrame(self, "HT")
            vTTC=FieldFrame(self, "TTC")
            vTVA=FieldFrame(self, "TVA")
            vHT.inField.bind("<FocusOut>", calc)  #où/comment gérer le "bind"??
     
        def calc(event):            # exemple de pré-calcul
            ht = vHT.getV()
            ttc = 1.2*ht
            tva=ttc-ht
            vTTC.setV(ttc)
            vTVA.setV(tva)
     
    # petit' frame étiquette + le champ à remplir
    class FieldFrame(Frame):
        def __init__(self, parent, etikt, inV=0):
            self.inV=StringVar()
            Frame.__init__(self, parent)
            self.pack(side=LEFT)
            self.etikV = Label(self, text=etikt).pack() 
            self.inField = Entry(self, textvariable=self.inV).pack()
            #self.inField.bind("<FocusOut>", calc)
     
        def getV(self):
            return inV.get()
     
        def setV(self, inVal):
            self.inV.set(inVal)
     
    mApp = MonApp()
    mApp.mainloop()

    Le code qui marche pour exprimer le fonctionnement attendu (dès que l'on quitte le champ HT les autres sont remplis avec une valeur par défaut, l'appui successif sur <TAB> par exemple permet de saisir rapidement lorsque les valeurs calculées par défaut s'avèrent correctes):
    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
    38
    39
    40
    41
    42
    43
    44
    from tkinter import *
     
    # une fenêtre pour saisir une ligne comptable par exemple
    class MonApp(Tk):               
        def __init__(self):
            Tk.__init__(self)
            self.title('MonApplication')
            num1=Numericals(self)
     
    # un frame regroupe les montants à saisir et/ou pré-calculés 
    class Numericals(Frame):
        def __init__(self, parent):
            Frame.__init__(self, parent=None)
            self.pack(side=LEFT)
            vHT=FieldFrame(self, "HT")
            vTTC=FieldFrame(self, "TTC")
            vTVA=FieldFrame(self, "TVA")
            vHT.inField.bind("<FocusOut>", calc)  #où/comment gérer le "binding"
     
        def calc(event):            # exemple de pré-calcul
            ht = vHT.getV()
            ttc = 1.2*ht
            tva=ttc-ht
            vTTC.setV(ttc)
            vTVA.setV(tva)
     
    # petit' frame étiquette + le champ à remplir
    class FieldFrame(Frame):
        def __init__(self, parent, etikt, inV=0):
            self.inV=StringVar()
            Frame.__init__(self, parent)
            self.pack(side=LEFT)
            self.etikV = Label(self, text=etikt).pack() 
            self.inField = Entry(self, textvariable=self.inV).pack()
            #self.inField.bind("<FocusOut>", calc)
     
        def getV(self):
            return inV.get()
     
        def setV(self, inVal):
            self.inV.set(inVal)
     
    mApp = MonApp()
    mApp.mainloop()
    merci de votre aide

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    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 741
    Par défaut
    Salut,

    Citation Envoyé par mc.jordan Voir le message
    Je ne sais même pas si l'intitulé est clair, débutant en python pas vraiment de base en poo, malgré mes recherches je n'arrive pas à transposer quelques lignes simples écrites moyennant une seule classe en un programme plus structuré qui fait appel à plusieurs classes.
    Si vous débutez avec Python et que vous n'avez aucune base en POO, pas étonnant que vous n'y arrivez pas. Ouvrez n'importe quel tuto. vous verrez qu'il y a plein de choses à apprendre avant d'aborder la POO avec Python et des tutos spécifiques à la POO qui n'a rien à voir avec Python.

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

  3. #3
    Membre régulier
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Janvier 2013
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2013
    Messages : 8
    Par défaut
    Bonjour et merci de votre réponse,
    Oui effectivement c'est pas étonnant que je n'y arrive pas, je pourrais aussi demander de l'aide une fois que j'y suis arrivé, juste comme ça pour discuter. Si je dis que je suis débutant c'est en toute humilité et en pensant que j'ai juste besoin d'un petit coup de main. J'ai appris la programmation avec le langage assembleur sur 8051 à une époque où le langage C était encore balbutiant, alors en reprenant l'exercice 40 ans plus tard et en abordant la poo c'est excitant mais forcément un peu difficile. Merci d'IMAGINER UNE SECONDE que j'ai parcouru des dizaines de tutos, des cours, des forums, compris pas mal de choses mais avec des lacunes puisque c'est sans avoir trouvé la solution. Donc j'essaie une autre voie et je n'ai pas l'habitude de demander de l'aide si je n'ai pas auparavant fait l'effort nécessaire. Tous les tutos rencontrés déclenchent un évènement à partir d'un bouton ou d'une touche clavier et dans ce cas ça me semble facile, mais jamais dans la configuration que je souhaite. Je ne vois pas ce qu'il faut mettre en place, je suis bloqué. Mais effectivement je peux aussi ne rien demander à personne. f.

  4. #4
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    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 741
    Par défaut
    Citation Envoyé par mc.jordan Voir le message
    Oui effectivement c'est pas étonnant que je n'y arrive pas, je pourrais aussi demander de l'aide une fois que j'y suis arrivé, juste comme ça pour discuter.
    Si vous postez un code dans lequel on trouve:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
            vHT.inField.bind("<FocusOut>", calc)  #où/comment gérer le "bind"??
     
        def calc(event):            # exemple de pré-calcul
            ht = vHT.getV()
    pas étonnant que çà ne marche pas.

    Vous n'avez pas compris ce que sont variables, leur portée et côté class comment définir un attribut, une méthode...
    Ce sont des concepts qui sont bien expliqués et illustrés avec des exercices corrigés dans tous les tutos.
    De deux choses l'une soit vous êtes passé un peu vite sur les chapitres qui vont bien, soit vous ne comprenez pas (et outre que le propos d'un forum de discussion ne soit pas de vous rabâcher ce que vous auriez pu/du trouver dans un tuto., il sera difficile de faire mieux).

    Merci d'IMAGINER UNE SECONDE que j'ai parcouru des dizaines de tutos, des cours, des forums, compris pas mal de choses mais avec des lacunes puisque c'est sans avoir trouvé la solution.
    Parcourir des tutos ne sert à rien.
    Vous devez en choisir un qui vous parle et vous appliquer à le suivre pendant un certain temps chapitre après chapitre, en essayant de faire les exercices proposés pour vous assurer que vous avez compris les concepts présentés dans les chapitres correspondants.
    Cela vous permet d'accumuler de l'expérience et des exemples de code que vous pourrez réutiliser dans différents projets. En plus vous avez une table des matières: facile de revoir un chapitre lorsqu'on a des difficultés avec les variables, les class,...


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

  5. #5
    Membre régulier
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Janvier 2013
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2013
    Messages : 8
    Par défaut
    Effectivement je n'ai pas tout compris, quelque chose m'échappe. Merci pour le temps passé.
    f.

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

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 910
    Par défaut
    Salut,

    Citation Envoyé par mc.jordan Voir le message
    J'ai appris la programmation avec le langage assembleur sur 8051 à une époque où le langage C était encore balbutiant...
    Ah les microcontrôleurs de cette famille... Maintenant c'est surtout l'Arduino (qui n'utilise pas les mêmes microcontrôleurs) qui est connu des jeunes...


    Sinon j'ai testé le code et c'est vrai qu'il y a beaucoup de choses qui posent problème...

    1- Il y a effectivement les problèmes soulevés par wiztricks mais juste avant il y a un autre problème dans vHT.inField.bind("<FocusOut>", calc)c'est que la propriété inField de vHT n'est pas ce que vous croyez (ce n'est pas un champs de saisie Entry) c'est un objet vide (None) !

    L'erreur (qu'on trouve plusieurs fois dans le code) vient de self.inField = Entry(self, textvariable=self.inV).pack()... Cette erreur est d'ailleurs signalée dans un bouquin, regardez ce chapitre 8.6. Composition d'instructions pour écrire un code plus compact, en particulier ce passage :

    Et dans ce cas, il faut obligatoirement utiliser deux instructions distinctes, l'une pour instancier le widget et l'autre pour lui appliquer ensuite la méthode de mise en page. Vous ne pouvez pas, par exemple, construire une instruction composée telle que :

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    entree = Entry(fen1).pack()              # faute de programmation !!!
    En apparence, cette instruction devrait instancier un nouveau widget et l'assigner à la variable entree, la mise en page s'effectuant dans la même opération à l'aide de la méthode pack(). Dans la réalité, cette instruction produit bel et bien un nouveau widget de la classe Entry(), et la méthode pack() effectue bel et bien sa mise en page dans la fenêtre, mais la valeur qui est mémorisée dans la variable entree est la valeur de retour de la méthode pack() : ce n'est pas la référence du widget. Et vous ne pouvez rien faire de cette valeur de retour : il s'agit d'un objet vide (None).

    Pour obtenir une vraie référence du widget, vous devez utiliser deux instructions :

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    entree = Entry(fen1)             # instanciation du widget
    entree.pack()
    2- Par rapport aux problèmes soulevés par wiztricks :
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
          vHT.inField.bind("<FocusOut>", calc)  #où/comment gérer le "bind"??
     
      def calc(event):            # exemple de pré-calcul
          ht = vHT.getV()

    Pour pouvoir tester j'ai dû faire quelques modifs :

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
         vHT.inField.bind("<FocusOut>", self.calc)  #où/comment gérer le "bind"??
     
      def calc(self, event):
          ht = vHT.getV()

    3- Mais même là ce n'est pas encore terminé...

    Car vHt n'est pas "connu" à l'intérieur de la fonction calc, vHT a été défini dans le constructeur :

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class Numericals(Frame):
        def __init__(self, parent):
            Frame.__init__(self, parent=None)
            self.pack(side=LEFT)
            vHT=FieldFrame(self, "HT")
            ...
    ...

    Pour pouvoir l'utiliser dans les autres méthodes comme calc j'ai utilisé self (lignes 5, 8 et 11) :

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class Numericals(Frame):
        def __init__(self, parent):
            Frame.__init__(self, parent=None)
            self.pack(side=LEFT)
            self.vHT = FieldFrame(self, "HT")
            ...
            # où/comment gérer le "binding"
            self.vHT.inField.bind("<FocusOut>", self.calc)
     
        def calc(self, event):       
            ht = self.vHT.getV()
            ttc = 1.2*ht
            ...
    ...

    3.1 La ligne ttc = 1.2*ht pose aussi problème car ht n'est pas un nombre comme vous le croyez mais une chaine de caractères, il faudrait rajouter une conversion juste avant : ht = float(self.vHT.getV())...



    Il y a encore d'autres problèmes mais là il y a déjà de quoi faire car il faut appliqué ce qui a été dit aux autres variables et propriétés...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Agir sur un widget depuis une autre classe
    Par Cenixosh dans le forum Débuter
    Réponses: 2
    Dernier message: 09/03/2017, 22h16
  2. reference sur le retour d'une fonction
    Par yan dans le forum C++
    Réponses: 7
    Dernier message: 21/11/2007, 16h42
  3. test sur le nom d'une fonction
    Par Art19 dans le forum C
    Réponses: 6
    Dernier message: 26/06/2006, 18h29
  4. Réponses: 5
    Dernier message: 13/10/2005, 12h46
  5. [Pl/pgSQL] Erreur sur l'execution d'une fonction.
    Par Floréal dans le forum PostgreSQL
    Réponses: 2
    Dernier message: 25/09/2005, 00h48

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