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 :

Pourquoi mes widgets ne sont pas indépendants ?


Sujet :

Tkinter Python

  1. #1
    Membre éprouvé
    Inscrit en
    Août 2010
    Messages
    1 124
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 1 124
    Points : 1 277
    Points
    1 277
    Par défaut Pourquoi mes widgets ne sont pas indépendants ?
    Bonjour à tous,

    Le but du code suivant est de permettre à l'utilisateur d'éditer les valeurs d'un dictionnaire. Le principe est assez simple : partant par exemple du dict
    {"par1":"value1" , "par2":["possibilite1","possibilite2"]},
    la fonction apply() va créer ce qui ressemble à:
    TEXT(par1) ENTRY(value1)
    TEXT(par2) MENUBUTTON(->possibilite1 / -> possibilite2)

    Jusque la, la fonction marche "bien" (voir la fonction main() pour un exemple).

    Maintenant, je veux interfacer deux dictionnaires distincts sur la même Frame. J'applique donc deux fois ma fonction apply(), et c'est la que le problème arrive: les widgets crées (leurs textvariables stringVar) ne sont pas indépendantes, alors qu'elles sont a priori crées dans des espaces de nommage différents. La fonction testindependance() illustre ce problème lorsque l'on saisir les valeurs dans l'un des deux dictionnaires, le changement se répercute à l'autre.

    Je ne comprends pas pourquoi. Est-ce un problème de lambda pur Python, ou un problème spécifique à Tk ? Je vous remercie par avance pour votre aide (ainsi que pour tout commentaire pour améliorer le code).

    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
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
     
    """
    DICTIONNARY INTERFACE FOR EDITING VALUES
    creates labels/edits/menubutton widgets in a TkFrame to edit dictionnary values
    use: apply(frame,dict,position)
    """
     
    import Tkinter as tk
     
    def cbMenu(controlV,value,btn= None):
        controlV.set(str(value))
        if not (btn== None):
            btn.config(text= str(value))
     
    def updateMB(ctrlV, value):
        ctrlV.set(value)
     
    def doLambda(f,*args):
        """Tips: Create lambda within for loop with fixed local variable
        without interference across iterations"""
        def g(): return f(*args)
        return g
     
     
    def apply(root,d,pos):
        """Creates interface for dictionnary d in root at given grid position """
        "TODO: repercuter kwargs"
        (x,y,w,h)= pos
        lbs= []    
        saisies= dict()    
        entries= dict()
        for (n,(k,v)) in enumerate(d.iteritems()):  
            assert (k not in saisies)        
            l= tk.Label(root,text=str(k))
            l.grid(row=n+x,column=y)               
            if isinstance(v,list):
                """value= list => multiple choice => use menubutton"""            
                saisies[k]= tk.StringVar(name=str(n),value= str(v[0]))            
                ent=tk.Menubutton(root,textvariable=saisies[k],relief="sunken")
                ent.m=tk.Menu(ent,tearoff=0)
                ent.config(menu=ent.m)    
                for (kk,possible) in enumerate(v):             
                    possibleSaved= "%s" %possible                 
                    ent.m.add_command(label=str(possible), command= doLambda(updateMB
                                                                     ,saisies[k],str(d[k][kk]) ) )
                    print possible
            else:         
                """value is not a list => classical edit => use Entry""" 
                saisies[k]= tk.StringVar(name=str(n),value= str(v))   
                ent= tk.Entry(textvariable=saisies[k])#,width=30)
            ent.grid(row=n+x,column=y+1)     
            entries[k]= ent
        return saisies
     
     
     
    def main():
        "EXAMPLE"
        root = tk.Tk()
        #d= {'oui':1, 'non':'non'}
        d= {'oui':1,'a':'b', 'non':['?','!non'],'mode':[1.1,2.1,3.1]}
     
        v= tk.StringVar(value= "Open File Dialog")
     
        m=tk.Menubutton(root,textvariable=v,relief="raised")
        m.grid(row=2,column=1)
        mm=tk.Menu(m,tearoff=0)
        tk.Button(root, textvariable=v, command=lambda:v.set('oui')).grid(row=1,column=1)
        mm.add_command(label="go", command=lambda: cbMenu(v,"non"))
        m.config(menu=mm) 
     
        s= apply(root,d,(0,2,0,0))
        print isinstance(d, dict)
        root.mainloop()
        #print d
        print s
        for (k,v) in s.iteritems():
            print str(k), '->',str(v.get())
     
    def testindependance():
        root = tk.Tk()
        d= {'oui':1,'a':'b', 'non':['?','!non'],'mode':[1.1,2.1,3.1]}
        s= apply(root,d,(0,2,0,0))
     
        dd= {'oui':1,'a':'b', 'non':['?','!non'],'mode':[1.1,2.1,3.1]}
        ss= apply(root,dd,(0,5,0,0))
     
        print "s =",s
        print "ss=",ss
     
        print isinstance(d, dict)
        root.mainloop()
        #print d
        print s
        for (k,v) in s.iteritems():
            print str(k), '->',str(v.get())     
     
    if __name__ == '__main__':
        # main()
        testindependance()

  2. #2
    Membre éprouvé
    Inscrit en
    Août 2010
    Messages
    1 124
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 1 124
    Points : 1 277
    Points
    1 277
    Par défaut
    Il suffit d'enlever les arguments
    qui donnaient le même nom pour différentes "instances"

    Désolé de polluer le forum. Je reste quand même interessé par tout commentaire pour améliorer le code.

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

Discussions similaires

  1. [C#Express 2008] Pourquoi mes CustomControls ne sont pas utilisables en mode Design ?
    Par neguib dans le forum Windows Presentation Foundation
    Réponses: 5
    Dernier message: 27/11/2008, 10h43
  2. Réponses: 26
    Dernier message: 05/02/2007, 16h57
  3. Réponses: 7
    Dernier message: 22/09/2006, 01h28
  4. [WebForms][2.0] Pourquoi mes liens ne sont-ils pas valides ?
    Par ben_popcorn dans le forum Général Dotnet
    Réponses: 3
    Dernier message: 19/09/2006, 16h11

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