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 :

Récupérer une variable, initialisée dans une fonction associée à un évenement


Sujet :

Tkinter Python

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 11
    Points : 5
    Points
    5
    Par défaut Récupérer une variable, initialisée dans une fonction associée à un évenement
    Bonjour,
    J'essaie d'éviter d'utiliser les variables "global".
    Dans l'utilisation classique d'une fonction le "return a" me permet de
    récupérer la variable "a" dans mon programme principal.
    Comment faire quand la fonction est appelée par un "event"?
    par exemple dans le code ci dessous le <print "a = ", a> est en erreur.


    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
    from Tkinter import *  
     
    def clic_dans_lbx1(event):
        a = 44   
        return a
     
    root = Tk()
    listbox1 = Listbox(root, width=50, height=6)
    listbox1.grid(row=0, column=0)
    bou1 = Button(root, text='QUITTER', command = root.quit)
    bou1.grid(row=3, column=3)
     
    listbox1.bind('<ButtonRelease-1>', clic_dans_lbx1)
     
    root.mainloop()
     
    print "a = ",  a
     
    root.destroy()
    Y a t'il une solution sans utiliser "global a" ?
    Merci.

  2. #2
    Membre habitué
    Inscrit en
    Avril 2010
    Messages
    99
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations forums :
    Inscription : Avril 2010
    Messages : 99
    Points : 143
    Points
    143
    Par défaut
    Bonjour,

    tout d'abord, c'est une bonne idée d'éviter les variables globales.

    Plusieurs remarques.

    Tout d'abord il faut comprendre que, quand tu fais "return a",
    tu ne renvois pas la variable a mais le contenu de cette variable (ici 44).
    En faisant return a, rien ne te permet d'indiquer que tu veux associer ce contenu à la variable a.
    Tu aurais fait directement return 44, ça serait revenu strictement au même.

    Bon, ensuite dans la méthode bind, la valeur renvoyée par la fonction donnée en argument à bind n'est pas pris en compte, donc ici ton return 44 ne sert à rien.

    Je ne sais pas s'il est possible faire ce que tu veux (c'est à dire si j'ai bien compris que lorsque tu cliques sur la list box, ça affecte 44 à une variable et que le contenu de cette variable est renvoyée lorsque la fenêtre est fermée) sans utiliser des variables globales et sans créer de classes.

    La meilleure solution pour ne plus utiliser de variables globales est d'utiliser des classes et des objets mais la façon de concevoir un programme orienté objet est différente de celle d'un programme "impératif" et il faut revoir la façon d'aborder le problème (je parle dans le cas général).

    Je ne sais pas si tu t'y connais en programmation orienté objet, je donnerai des exemples en conséquence (parce que balancer un exemple si tu ne le comprends pas, ça sert un peu à rien).

  3. #3
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Bonsoir,

    globals en Python n'est pas aussi dramatique que cela mais... bon.
    Si vous ne voulez pas que "a" soit "global", il faut le mettre "dans" une chose qui soit accessible au handler et à print.

    Comme le handler recoit un event avec le widget correspondant, une solution pourrait être de dériver Listbox pour lui ajouter une variable adhoc dedans.

    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
    from Tkinter import *  
     
    class MyListbox(Listbox):
     
       def __init__(self, *args, **kwds):
           Listbox.__init__(self, *args, **kwds)
           self.a = 0
     
    def clic_dans_myListbox(event):
        assert isinstance(event.widget, MyListbox)
        event.widget.a = 44
     
     
    root = Tk()
    listbox1 = MyListbox(root, width=50, height=6)
    listbox1.grid(row=0, column=0)
    bou1 = Button(root, text='QUITTER', command = root.quit)
    bou1.grid(row=3, column=3)
     
    listbox1.bind('<ButtonRelease-1>', clic_dans_myListbox)
     
    root.mainloop()
     
    print "a = ",  listbox1.a
    Une autre solution serait de mettre 'a' dans un myGlobals "singleton".
    De ce fait, le handler et print accèderont au même état de myGlobals sans le transporter via le Widget.

    Ca donne...
    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
    from Tkinter import *  
     
    class MyGlobals(): pass
     
    def clic_dans_myListbox(event):
        MyGlobals.a = 44
     
    if __name__ == '__main__':
     
        root = Tk()
        listbox1 = Listbox(root, width=50, height=6)
        listbox1.grid(row=0, column=0)
        bou1 = Button(root, text='QUITTER', command = root.quit)
        bou1.grid(row=3, column=3)
     
        listbox1.bind('<ButtonRelease-1>', clic_dans_myListbox)
     
        root.mainloop()
     
        print "a = ",  MyGlobals.a
    Les deux exemples précédents sont du copie&coller de ce qu'on peut imaginer faire avec les langages POO normaux.

    Un truc plus Python... maintenant:
    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 *  
     
    class Clics(object):
     
         def __init__(self):
             self.a = None
     
         def handler(self, event):
             self.a = 44
     
         def __str__(self):
             return 'clics: %d' % self.a
     
    if __name__ == '__main__':
     
        clics = Clics()
     
        root = Tk()
        listbox1 = Listbox(root, width=50, height=6)
        listbox1.grid(row=0, column=0)
        bou1 = Button(root, text='QUITTER', command = root.quit)
        bou1.grid(row=3, column=3)
     
        listbox1.bind('<ButtonRelease-1>', clics.handler)
     
        root.mainloop()
     
        print "a = ",  clics
    Ca fait quoi cette chose? Ben plutôt que de passer à "bind" une fonction toute bête, on lui passe la méthode de l'instance de 'Clics'.

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

  4. #4
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonjour,

    Et une solution plus Tk

    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
    from Tkinter import *
     
    def clic_dans_lbx1(event=None):
        a.set(44)
     
     
     
    root = Tk()
     
    a=IntVar()
     
    listbox1 = Listbox(root, width=50, height=6)
    listbox1.grid(row=0, column=0)
    bou1 = Button(root, text='QUITTER', command = root.quit)
    bou1.grid(row=3, column=3)
     
    listbox1.bind('<ButtonRelease-1>', clic_dans_lbx1)
     
    root.mainloop()
     
    print "a = ",  a.get()
     
    root.destroy()
    @+
    Merci d'utiliser le forum pour les questions techniques.

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 11
    Points : 5
    Points
    5
    Par défaut
    Merci pour ces réponses rapides.
    Apparemment vous êtes tous les trois (Biribibi, Wiztricks, Pausekawa) d'accord pour me dire que la solution est dans la POO... que je ne maitrise pas.

    Bon OK. J'attendais l'occasion de m'y plonger. Voilà un point de départ.
    J'attends encore qq jours pour dire mon pb résolu au cas ou il y aurait d'autres ouvertures...
    dans l'immédiat l'approche de Pausekawa m'apparait plus simple à mettre en oeuvre.
    Qu' en dites vous ?

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut

    Merci pour ces réponses rapides.
    Apparemment vous êtes tous les trois (Biribibi, Wiztricks, Pausekawa) d'accord pour me dire que la solution est dans la POO... que je ne maitrise pas.
    Un des intérêt de la POO est d'apporter des solutions non pour "éviter" d'avoir trop de variables "globales" mais pour les ranger dans des "boîtes" (classes, instances, ...)...
    Note: Vous pouvez vous permettre d'en avoir plus sans vous prendre les pieds dans le tapis grâce au rangement.

    Enlevez la POO, il vous reste la possibilité de structurer votre code en vous appuyant sur les "modules" - i.e. qu'est ce qui sera visible ou pas à l'extérieur d'un module. [ C'est ce qu'on fait en C de base ]


    Exemple:
    Créons un module myglobals.py contenant
    Depuis le "main", nous allons pouvoir "l'importer" et accéder à "a"

    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
    from Tkinter import *  
    import myglobals
     
    def clic_dans_myListbox(event):
        myglobals.a = 44
     
    if __name__ == '__main__':
     
        root = Tk()
        listbox1 = Listbox(root, width=50, height=6)
        listbox1.grid(row=0, column=0)
        bou1 = Button(root, text='QUITTER', command = root.quit)
        bou1.grid(row=3, column=3)
     
        listbox1.bind('<ButtonRelease-1>', clic_dans_myListbox)
     
        root.mainloop()
     
        print "a = ",    myglobals.a
    Note: La POO vous permet d'ajouter des boîtes appelées classes dans les "modules", des classes dans des classes... et des instances de classes!!!
    Que de tiroirs!!!

    J'attends encore qq jours pour dire mon pb résolu au cas ou il y aurait d'autres ouvertures...
    dans l'immédiat l'approche de Pausekawa m'apparait plus simple à mettre en oeuvre.
    Vous faites ce que vous voulez mais l'approche PauseKawa ne me semble pas répondre à votre question: le "a" auquel accède le 'handler' clic_... est dans "globals" et que votre a soit un integer ou un IntVar.

    La différence est que 'a.set' étant une méthode (un attribut fonctionnerait) cela force l'interpréteur à regarder dans globals (avec a = 44, il crée l'entier dans locals sans plus de question).

    Même si ca fonctionne, d'où vient le "a"? De global!!!
    Pourquoi ne pas le dire?
    Là on masque un effet de bord qui fonctionne pour les instances de "classes" et pas pour les instances de types simples...

    Et mettre "global a" est bien ce que vous ne vouliez pas faire au départ?

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

  7. #7
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonjour,

    Citation Envoyé par wiztricks Voir le message
    Vous faites ce que vous voulez mais l'approche PauseKawa ne me semble pas répondre à votre question: le "a" auquel accède le 'handler' clic_... est dans "globals" et que votre a soit un integer ou un IntVar.
    Exact, j'avais considérer les class variables tk comme les exemples donnés plus haut sans trop prendre en compte la question. C'est vrais que je la place dans global et que c'est cela qui fais que a est visible. Réponse à ne pas retenir donc.
    Merci pour la réponse wiztricks.

    @+
    Merci d'utiliser le forum pour les questions techniques.

  8. #8
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Yup,

    Mais je viens de comprendre en relisant http://www.developpez.net/forums/d91...l/#post5180723 que ce j'appelle effet de bord est "documenté" proprement.

    En clair, une fonction peut accéder aux variables "globales" en lecture seule.
    i.e. pour pouvoir les modifier il faut dire "global"...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    a = 0
    def brico():
        b = a    # ok car a est accessible en lecture
        a = 44  # plante car on ne sait plus qui est 'a'
    brico()
    Là ou ca se corse (et c'est le sujet de l'autre fil de discussion) c'est quand "a" n'est pas un type simple mais l'adresse d'une collection. On peut récupérer celle-ci "en lecture" et modifier le contenu de la collection sans soucis.

    Note: c'est ce qui se passe lorsqu'on fait "a = IntVar()".

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

  9. #9
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonjour,

    Comme il fallait bien que je m'en sorte par une pirouette et puisque une fonction est un objet.

    Sur l'exemple de wiztricks :

    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
    from Tkinter import *  
     
    def clic_dans_lbx1(event):
        if 'a' in dir(clic_dans_lbx1):
            clic_dans_lbx1.a += 1
        else: clic_dans_lbx1.a = 0
     
    root = Tk()
    listbox1 = Listbox(root, width=50, height=6)
    listbox1.grid(row=0, column=0)
    bou1 = Button(root, text='QUITTER', command = root.quit)
    bou1.grid(row=3, column=3)
     
    listbox1.bind('<ButtonRelease-1>', clic_dans_lbx1)
     
    root.mainloop()
     
    print "a = ",  clic_dans_lbx1.a
     
    root.destroy()
    C'est juste pour sortir la tête haute (avec une goutte de plagia, j'avoue)

    @+

    Edit pour carnussien : Les meilleures réponses sont celles de wiztricks et personnellement j'utilise en import une classe pour mes globals (Voir class MyGlobals(): pass) et si c'est pour du calcul je fais une locale mavar=MyGlobals.mavar.
    Merci d'utiliser le forum pour les questions techniques.

  10. #10
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 11
    Points : 5
    Points
    5
    Par défaut
    Bonsoir,
    Merci, c'est exactement le genre de discussion que j'espérais.
    J'ai suffisamment de matière à réflexion.
    je marque donc le sujet comme résolu.
    A+

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

Discussions similaires

  1. Réponses: 9
    Dernier message: 23/06/2009, 10h54
  2. [MySQL] récupérer l'item selctionné d'une liste déroulante dans une variable php
    Par car0line dans le forum PHP & Base de données
    Réponses: 10
    Dernier message: 22/04/2009, 14h30
  3. [PHP-JS] Récupérer une variable JS dans une variable PHP
    Par Perceuse-Killer dans le forum Langage
    Réponses: 2
    Dernier message: 07/02/2008, 15h34
  4. Réponses: 4
    Dernier message: 23/02/2007, 09h37
  5. récupérer une variable javascript dans une variable java
    Par tx dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 06/07/2006, 17h55

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