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 :

Génération automatique de boutons et actions liés à différentes méthodes [Python 2.X]


Sujet :

Tkinter Python

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2014
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Février 2014
    Messages : 7
    Points : 6
    Points
    6
    Par défaut Génération automatique de boutons et actions liés à différentes méthodes
    Bonjour à tous.

    Je me suis mis récemment au code Python et je rencontre un problème avec la fonction getattr.
    Le code code que j'ai créé me permet de créer des boutons de manière dynamique, mais j'aimerais que les actions de ces boutons ne fassent pas forcément appel à la même méthode. Pour cela j'utilise la méthode getattr pour récupérer la méthode que je veux associer au bouton. Mais à chaque fois que je lance le programme les boutons récupèrent la méthode du dernier bouton généré.
    Pouvez-vous m'aider?
    Merci.

    Voici le code que j'ai créé:
    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
    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
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    ###-------------------------------------------------------------------------------
    ###-------------------------------------------------------------------------------
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    ### -*- coding: iso-8859-1 -*-
     
    import sys
    import os
    import csv
    import Tkinter
    from Tkinter import *
    import tkFileDialog
    from tkFileDialog import *
    from types import *
     
     
    class simpleapp_tk(Tkinter.Tk):
        #variables de la classe
        initDirectory=u"C:/"
        globalvaluelabel=u"valuelabel"
     
        def __init__(self,parent):
            Tkinter.Tk.__init__(self,parent)
            self.parent=parent
            self.grid()
            self.initialize()
     
        #Fonction d'Initialisation de la classe
        def initialize(self):
            self.InitIHM()
            self.InitFilesPath()
     
        def InitIHM(self):
            self.InitArrays()
            self.InitButtons()
            self.InitRadioButtons()
            self.InitLabels()
            ##self.grid_columnconfigure(1,weight=1)
            self.grid_columnconfigure(2,weight=1)
            self.resizable(True,False)
     
        def InitArrays(self):
            self.MODESLIST=[
                (1,u"choix1",),
                (2,u"choix2"),
                (3,u"choix3"),
                ]
            self.BUTTONSLIST=[
                (1,True,u"OnButtonClickFile",u"boutonfichier1"),
                (2,True,u"OnButtonClickFile",u"boutonfichier2"),
                (3,True,u"OnButtonClickFile",u"boutonfichier3"),
                (4,True,u"OnButtonClickFile",u"boutonfichier4"),
                (5,True,u"OnButtonClickFile",u"boutonfichier5"),
                (6,True,u"OnButtonClickDirectory",u"boutondossier1"),
                (7,True,u"OnButtonClickDirectory",u"boutondossier2"),
                (8,False,u"Executer",u"Executer")
                ,]
            self.LABELSLIST=[
                (1,"e","white","blue",1),
                (2,"e","white","blue",1),
                (3,"e","white","blue",1),
                (4,"e","white","blue",1),
                (5,"e","white","blue",1),
                (6,"e","white","blue",1),
                (7,"e","white","blue",1)
                ,]
            self.BUTTONS=[]
            self.LABELS=[]
            self.FILES={}
     
        def InitFilesPath(self):
            pos=-1
            if len(sys.argv)>1:
                for arg in sys.argv[1:8]:
                    pos=pos+1
                    self.LABELS[pos].set(arg)
     
        #Fonction d'ajout de tous les boutons de l'IHM
        def InitButtons(self):
            for pos,hasargs,cmd,texte in self.BUTTONSLIST:
                button=None
                ##Vérification si il y a des arguments à attacher aux boutons
                if hasargs==True:
                    fnc=getattr(self,cmd)(texte,pos)
                    button=self.AddButton(nomcommande=lambda x=pos,y=texte:(fnc),texte=texte,poscol=0,posrow=pos)
                else:
                    fnc=getattr(self,cmd)()
                    button=self.AddButton(nomcommande=lambda :(fnc),texte=texte,poscol=0,posrow=pos)
                self.BUTTONS.append(button)
     
        #Fonction d'ajout de tous les Radioboutons de l'IHM
        def InitRadioButtons(self):
            self.valueradiobutton=IntVar()
            for mode,texte in self.MODESLIST:
                radiobutton=self.AddRadioButton(nomcommande=self.Selection,valeur=self.valueradiobutton,texte=texte,select=mode,poscol=3,posrow=mode)
     
        #Fonction d'ajout de tous les boutons de l'IHM
        def InitLabels(self):
            for pos,ancrage,color1,color2,columnspan in self.LABELSLIST:
                va = StringVar()
                etiquette=None
                etiquette=self.AddLabel(nomlabel=va,lanchor=ancrage,lfg=color1,lbg=color2,poscol=2,posrow=pos,colspan=columnspan)
                self.LABELS.append(va)
     
        #Fonction permettant de créer un Bouton
        def AddButton(self,nomcommande,texte=u"Button",poscol=0,posrow=0):
            # Creation d'un nouveau bouton.
            bouton = Tkinter.Button(self,text=texte,width=25,command=nomcommande)
            bouton.grid(column=poscol,row=posrow)
            return bouton
     
        #Fonction permettant de créer un RadioBouton
        def AddRadioButton(self,nomcommande,valeur,texte=u"RadioButton",select=0,poscol=0,posrow=0):
            radiobouton=Tkinter.Radiobutton(self,variable=valeur,value=select,text=texte,command=nomcommande)
            radiobouton.grid(column=poscol,row=posrow,sticky="W")
            return radiobouton
     
        #Fonction permettant de créer un RadioBouton
        def AddLabel(self,nomlabel,lanchor,lfg,lbg,poscol=0,posrow=0,colspan=0):
            label=Tkinter.Label(self,textvariable=nomlabel,anchor=lanchor,width=45,fg=lfg,bg=lbg)
            label.grid(column=poscol,row=posrow,columnspan=colspan,sticky=(E,W))
            return label
     
        def OnButtonClickFile(self,name,number):
            valeur=number-1
            #savoir si on est dans la liste des Labels
            if (valeur<len(self.LABELS)) and (valeur>=0):
                if self.LABELS[valeur].get():
                    tmppath=self.LABELS[valeur].get()
                else:
                    tmppath=self.initDirectory
                #Modification ou suppression de la valeur dans le dictionnaire
                filename=askopenfilename(parent=self.parent,initialdir=tmppath,title=name,filetypes=[('all', '*')])
                if filename:
                    self.FILES[name]=filename
                    self.LABELS[valeur].set(self.FILES[name])
                txt=str(self.LABELS[valeur])
            else:
                txt=u"Failed No values"
            #print txt
     
        def OnButtonClickDirectory(self,name,number):
            valeur=number-1
            #savoir si on est dans la liste des Labels
            if (valeur<len(self.LABELS)) and (valeur>=0):
                if self.LABELS[valeur].get():
                    tmppath=self.LABELS[valeur].get()
                else:
                    tmppath=self.initDirectory
                directoryname=askdirectory(parent=self.parent,initialdir=tmppath,title=name,mustexist=False)
                if directoryname:
                    self.FILES[name]=directoryname
                    self.LABELS[valeur].set(self.FILES[name])
                txt=str(self.LABELS[valeur])
            else:
                txt=u"Failed No values"
            #print txt
     
        def Selection(self):
            valeur = self.valueradiobutton.get()-1
            if (valeur<len(self.MODESLIST)) and (valeur>=0):
                var=u"You selected the option " + str(valeur+1) + " " + self.MODESLIST[valeur][1]
            else:
                var=u"Error"
            print var
     
        def Executer(self):
            pass
     
     
     
    #Fonction Global du programme Python
    def Test():
    	print u"sucess"
    #Fonction Global du programme Python
    def fonctionVide():
    	pass
     
    if __name__ == '__main__':
        app = simpleapp_tk(None)
        app.title(u"Prog Test")
        app.mainloop()

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

    On peut supposer que la portion de code intéressante est:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
        def InitButtons(self):
            for pos,hasargs,cmd,texte in self.BUTTONSLIST:
                button=None
                ##Vérification si il y a des arguments à attacher aux boutons
                if hasargs==True:
                    fnc=getattr(self,cmd)(texte,pos)
                    button=self.AddButton(nomcommande=lambda x=pos,y=texte:(fnc),texte=texte,poscol=0,posrow=pos)
                else:
                    fnc=getattr(self,cmd)()
                    button=self.AddButton(nomcommande=lambda :(fnc),texte=texte,poscol=0,posrow=pos)
                self.BUTTONS.append(button)
    Dans un premier temps, il faut revoir la construction "nomcommande=lambda x=pos,y=textefnc)"
    Soit une fonction f acceptant name et number en paramètres:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    >>> def f(name, number):
    ...     print 'f: name=', name, 'number=', number
    ...
    >>>
    "lambda" va permettre de construire d'autres fonctions en gelant certains paramètres:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    >>> f1 = lambda: f('xxx', 1)
    >>> f2 = lambda: f('zzz', 2)
    >>> f1()
    f: name= xxx number= 1
    >>> f2()
    f: name= zzz number= 2
    >>>
    La ou çà se complique, c'est quand on veut construire ces fonctions dans une boucle for:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    >>> fl = []
    >>> for x in range(3):
    ...     t = lambda: f('zzz', x)
    ...     fl.append(t)
    ...
    >>> for z in fl: z()
    ...
    f: name= zzz number= 2
    f: name= zzz number= 2
    f: name= zzz number= 2
    >>>
    Le "x" sera toujours le dernier (2)... car le contexte d'une boucle n'est pas imbriqué.
    Pour y pallier, on passe la valeur ad hoc en paramètre par défaut:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    >>> fl = []
    >>> for x in range(3):
    ...     t = lambda x=x: f('zzz', x)
    ...     fl.append(t)
    ...
    >>> for z in fl: z()
    ...
    f: name= zzz number= 0
    f: name= zzz number= 1
    f: name= zzz number= 2
    >>>
    Une difficulté supplémentaire sera d'avoir la fonction passée au lambda "variable"...
    Ajoutons une fonction "g":
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    >>> def g(name, number):
    ...     print 'g: name=', name, 'number=', number
    ...
    Puis on recommence:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >>> fl = []
    >>> for x, t in enumerate((f, g)):
    ...     u = lambda x=x: t('zzz', x)
    ...     fl.append(u)
    ...
    >>> for z in fl: z()
    ...
    g: name= zzz number= 0
    g: name= zzz number= 1
    >>>
    Même phénomène que pour le "x": c'est toujours la dernière fonction qui est appelée...
    Et même solution:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >>> fl = []
    >>> for x, t in enumerate((f, g)):
    ...     u = lambda x=x, t=t: t('zzz', x)
    ...     fl.append(u)
    ...
    >>> for z in fl: z()
    ...
    f: name= zzz number= 0
    g: name= zzz number= 1
    >>>
    Dans tous les cas, "lambda" et boucle "for" ont des comportements qui méritent d'être décortiquées et maîtrisés...
    note: et vous voyez qu'on n'a pas besoin de getattr, tkinter et de button construits à la volée pour exposer, reproduire,...

    - W

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2014
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Février 2014
    Messages : 7
    Points : 6
    Points
    6
    Par défaut Problème résolu


    Salut,
    Merci pour la réponse. J'ai testé et ça marche!!

    Merci encore pour ton aide.

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 15/04/2011, 02h16
  2. 3 boutons = 3 actions différentes / COMMENT FAIRE ?
    Par xgr8 dans le forum Composants graphiques
    Réponses: 5
    Dernier message: 11/11/2010, 00h31
  3. action avec un seul bouton sur plusieurs MC différents
    Par cece2000 dans le forum ActionScript 1 & ActionScript 2
    Réponses: 1
    Dernier message: 22/04/2008, 11h33
  4. [Plugin]Gestion de génération automatique de code
    Par Maggic dans le forum Eclipse Java
    Réponses: 1
    Dernier message: 11/05/2004, 11h35

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