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 :

'Additionneuse' à bande (essai prétexte à la manip des widgets)


Sujet :

Tkinter Python

  1. #1
    Membre régulier
    Homme Profil pro
    retraité
    Inscrit en
    Septembre 2010
    Messages
    102
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : retraité
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Septembre 2010
    Messages : 102
    Points : 71
    Points
    71
    Par défaut 'Additionneuse' à bande (essai prétexte à la manip des widgets)
    Bonjour à tous,

    Bien qu'elle fonctionne parfaitement, la finalité en elle même de l'application ci-jointe n'a pas grand intérêt à part celui d'être le prétexte:

    - à la manipulation des widgets
    - à la factorisation des Entry et Label (courtoisie wiztricks, merci à lui)
    - au contrôle de saisies float y compris négatives. (cf. post. de paussekawa)
    - à la compréhension de la fabrication des classes

    - mais aussi à la tentative ratée de regrouper la validation des entrées dans la classe Saisie.

    Je me demande en effet (et peut être à tort d'ailleurs!) s'il ne serait pas plus judicieux, dans cet exercice, que la fonction de validation ici: 'OnValidate()' soit une s/fonction de la classe Saisie.

    C'est ce que je n'ai pas réussi à faire.

    je cherche un 'coup de main' et un avis à ce sujet.
    A résultat final identique, ai-je employé la bonne façon pour le faire ?

    A+
    L.P.

    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
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    from tkinter import *  
     
    class Saisie(object):
        def __init__(self):
            "Création des Entry contôlées en quantité selon la demande "
        def crea(z):
    #        print(z)
            for z in range(-1,z):
                name = 'myvars-%d' % (z+1)
                v = myvars[name] = StringVar(name=name) #; print(v,name)
                v.trace_variable("w", OnValidate)
     
                entry = Entry(root, textvariable =v, name="entry%d" %(z+1))
                entry.grid(row=z+1,column =0)
                entries.append(entry)  ## ajout dans la liste
                entry.bind('<Return>', change)
                entry.bind('<Tab>', affiche)
                entry.bind('<Shift-Tab>', affiche)
                entry.bind('<Button-1>', affiche)
                entry.bind('<Up>', changeUp)
                entry.bind('<Down>', change)
     
                etq='etq-%d' %(z+1)
                etq=Label(width=20, text='')
                etq.grid(row=z+1,column =1)
                etiq.append(etq)  ## ajout dans la liste
            e1.destroy() #; print('destroy e1')
            ee.destroy() #; print('destroy ee')
            entries[0].focus_set()
    ## ----       
    def OnValidate(name, index, mode):
        idx=int(name[7:]); # index du nom de la StringVar
        var = myvars.get(name)
        if var.get().startswith('.'):
            q=root.focus_displayof() ## idem que les 2 lignes ci-dessus
            q.insert(0,'0.')         ## evite de rechercher l'index
        elif var.get().startswith('-.'):
            entries[idx].delete(0,END)   ## code avec l'index
            entries[idx].insert(0,'-0.') ## même résultat       
        i=0
        for c in var.get():
            i+=1
            if not c.isdigit() and c not in '.-' or (c=='-' and i > 1):
                root.event_generate('<BackSpace>')
     
        if i > 1:
            try:
                s=float(var.get())
            except:
                root.event_generate('<BackSpace>')
        root.event_generate('<End>')
    ## ----   
     
    def change(event):
        root.event_generate('<Tab>')
     
    def changeUp(event):
        root.event_generate('<Shift-Tab>')
     
    def affiche(event):
        w=event.widget  # ; print(w,w.get())
        ww=str(w)
        idx=int(ww[6:]) # ; print('w.idx:',idx)
        result=0.0 ; r = 0
     
        for i in range(0,z+1):
    #        print('z',z)
            ri=entries[i].get() #; ri=float(ri) ; print('ri',ri)
            if ri != '':
                r += float(entries[i].get())
                etiq[i].config(text='s/tot =  {:8.4f}'.format(r),anchor=E)
            else:
                etiq[i].config(text='')
     
            etqTotv.config(text='{:10.2f}'.format(r))
     
    def valid(event=None):
        global z
        try:
            z=int(e1.get())-1
            if z <= 45: ##; print(z)
                Saisie.crea(z)
            else: e1.set(0)    
        except:
            e1.delete(0,END)
            return 0
     
    ### fenêtre principale ***
    root = Tk()
    root.title("** Additionneuse **")
     
    entries = []
    myvars = {}
    etiq = [] 
    z=100 ## nombre de lignes maxi
    eeVar=StringVar()
    ee=Entry(root, textvariable=eeVar, width=30)  
    ee.grid(row=0,column =0)
    eeVar.set('Combien de lignes ?')
    e1=Entry(root, validate='focusout', vcmd=valid)
    e1.grid(row=0,column =1)
    e1.bind('<Return>', valid)
    e1.focus_set()
     
    etqTotx=Label(width=20, text='Total général:', anchor=E, font='weight -14 bold')
    etqTotx.grid(row=z+2,column =0)
    etqTotv=Label(font='weight -16 bold', fg='blue',width=20, text='0.0')
    etqTotv.grid(row=z+2,column =1)
     
    root.mainloop()

  2. #2
    Expert éminent

    Avatar de deusyss
    Homme Profil pro
    Expert Python
    Inscrit en
    Mars 2010
    Messages
    1 659
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Expert Python
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 659
    Points : 8 442
    Points
    8 442
    Par défaut
    Salut,

    Je suis pas un grand expert en TK (plutot GTK); par contre programmer des softs, ça je connais bien.

    Donc quelques conseils pour améliorer ton code.

    Pour commencer, en première ligne, ajouter # -*- coding: utf-8 -*-, ce qu'il ne faut jamais oublier. Cela permet de préciser l'encodage de ton code. Ensuite, à la fin de ton code, un ajout de if __name__ == "__main__":. "__name__" est une variable assigné au lancement de ton code. Si "__name__" vaut "__main__" alors c'est que ton module a été lancé en direct.

    Dans mes cours, je recommande à mes étudiants de le mettre systématiquement, même si c'est pour y marquer juste "None". Tu dois y placer ce qui va lancer le reste de ton code, que ce soit pour lancer ton soft, ou lancer des tests (TU par exemple).

    Enfin, tu as créé une classe Saisie. A ta place, j'aurais plutot créé une classe Ihm. Je m'explique: le rôle d'une classe est en quelque sorte de constitué un moule pour créer de nouveaux objets. Dans le cas d'un soft, ces moules vont etre l'IHM, des connections, des fichiers d'un certains formats, des BDD, ...; mais pas juste des morceaux de l'un ou de l'autre. C'est ce que tu as fait ici.

    Si tu as des questions n'hésite pas

    EDIT: petit ajout. Dans le __init__, remplace ta phrase par une docstring: """ <phrase> """; suivit de None
    "La connaissance appartient à tout le monde" (Film Antitrust)

    Tout le nécessaire pour Python:
    *News/Accueil *Cours/tutoriels *FAQ
    *Forums *Outils dédiés *Mon espace personnel avec mes Articles, Cours et Tutoriels

  3. #3
    Membre régulier
    Homme Profil pro
    retraité
    Inscrit en
    Septembre 2010
    Messages
    102
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : retraité
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Septembre 2010
    Messages : 102
    Points : 71
    Points
    71
    Par défaut
    Bonjour deusyss et merci pour ta réponse.

    Toutefois, si je peux me le permettre, la question était:

    << Je me demande en effet (et peut être à tort d'ailleurs!) s'il ne serait pas plus judicieux, dans cet exercice, que la fonction de validation ici: 'OnValidate()' soit une s/fonction de la classe Saisie.

    C'est ce que je n'ai pas réussi à faire.

    je cherche un 'coup de main' et un avis à ce sujet.

    A résultat final identique, ai-je employé la bonne façon pour le faire ? >>


    Quelle aurait-été la bonne façon ?

    Je crains que tu aies surestimé mes compétences en python que j'ai découvert seulement au printemps dernier avec pour support le livre de G.Swinnen (J'en suis à la page 180 ).
    (plus le .pdf du site plus pratique pour les recherches et je n'y trouve pas la trace de classe IHM).

    J'ai modifié le code selon tes conseils mais la question première reste posée.
    A+ et merci pour ces conseils.
    L.P.

    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
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    #-*- coding: utf-8 -*-
    from tkinter import *  ## -------- modif 001 ----------
     
    class Saisie(object):
        def __init__(self):
            """Création d'Entry contôlées en quantité selon la demande """
            None
        def crea(z):
    #        print(z)
            for z in range(-1,z):
                name = 'myvars-%d' % (z+1)
                v = myvars[name] = StringVar(name=name) #; print(v,name)
                v.trace_variable("w", OnValidate)
     
                entry = Entry(root, textvariable =v, name="entry%d" %(z+1))
                entry.grid(row=z+1,column =0)
                entries.append(entry)  ## ajout dans la liste
                entry.bind('<Return>', change)
                entry.bind('<Tab>', affiche)
                entry.bind('<Shift-Tab>', affiche)
                entry.bind('<Button-1>', affiche)
                entry.bind('<Up>', changeUp)
                entry.bind('<Down>', change)
     
                etq='etq-%d' %(z+1)
                etq=Label(width=20, text='')
                etq.grid(row=z+1,column =1)
                etiq.append(etq)  ## ajout dans la liste
            e1.destroy() #; print('destroy e1')
            ee.destroy() #; print('destroy ee')
            entries[0].focus_set()
    ## ----       
    def OnValidate(name, index, mode):
        idx=int(name[7:]); # index du nom de la StringVar
        var = myvars.get(name)
        if var.get().startswith('.'):
            q=root.focus_displayof() ## idem que les 2 lignes ci-dessus
            q.insert(0,'0.')         ## evite de rechercher l'index
        elif var.get().startswith('-.'):
            entries[idx].delete(0,END)   ## code avec l'index
            entries[idx].insert(0,'-0.') ## même résultat       
        i=0
        for c in var.get():
            i+=1
            if not c.isdigit() and c not in '.-' or (c=='-' and i > 1):
                root.event_generate('<BackSpace>')
     
        if i > 1:
            try:
                s=float(var.get())
            except:
                root.event_generate('<BackSpace>')
        root.event_generate('<End>')
    ## ----   
     
    def change(event):
        root.event_generate('<Tab>')
     
    def changeUp(event):
        root.event_generate('<Shift-Tab>')
     
    def affiche(event):
        w=event.widget  # ; print(w,w.get())
        ww=str(w)
        idx=int(ww[6:]) # ; print('w.idx:',idx)
        result=0.0 ; r = 0
     
        for i in range(0,z+1):
    #        print('z',z)
            ri=entries[i].get() #; ri=float(ri) ; print('ri',ri)
            if ri != '':
                r += float(entries[i].get())
                etiq[i].config(text='s/tot =  {:8.4f}'.format(r),anchor=E)
            else:
                etiq[i].config(text='')
     
            etqTotv.config(text='{:10.2f}'.format(r))
     
    def valid(event=None):
        global z
        try:
            z=int(e1.get())-1
            if z <= 45: ##; print(z)
                Saisie.crea(z)
            else: e1.set(0)    
        except:
            e1.delete(0,END)
            return 0
     
    if __name__== '__main__':
    ### fenêtre principale ***
        root = Tk()
        root.title("** Additionneuse **")
     
        entries = []
        myvars = {}
        etiq = [] 
        z=100 ## nombre de lignes maxi
        eeVar=StringVar()
        ee=Entry(root, textvariable=eeVar, width=30)  
        ee.grid(row=0,column =0)
        eeVar.set('Combien de lignes ?')
        e1=Entry(root, validate='focusout', vcmd=valid)
        e1.grid(row=0,column =1)
        e1.bind('<Return>', valid)
        e1.focus_set()
     
        etqTotx=Label(width=20, text='Total général:', anchor=E, font='weight -14 bold')
        etqTotx.grid(row=z+2,column =0)
        etqTotv=Label(font='weight -16 bold', fg='blue',width=20, text='0.0')
        etqTotv.grid(row=z+2,column =1)
     
        root.mainloop()

  4. #4
    Expert éminent

    Avatar de deusyss
    Homme Profil pro
    Expert Python
    Inscrit en
    Mars 2010
    Messages
    1 659
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Expert Python
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 659
    Points : 8 442
    Points
    8 442
    Par défaut
    J'essaie juste d'apporter un coup de main, et t'expliquant comment bien structurer ton code .

    Après l'expérience vient en apprenant .

    Pour repondre à ta question, si c'est bien le cas.
    "La connaissance appartient à tout le monde" (Film Antitrust)

    Tout le nécessaire pour Python:
    *News/Accueil *Cours/tutoriels *FAQ
    *Forums *Outils dédiés *Mon espace personnel avec mes Articles, Cours et Tutoriels

  5. #5
    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,

    J'ai des difficultés à comprendre l'utilité de la classe Saisie dans votre code.
    Si on reste dans les "basiques", une classe est une sorte de prototype servant à fabriquer des objets semblables.
    On peut en fabriquer un seul mais "fabriquer" passe par "instancier" i.e. voir l'expression Saisie() quelque part.
    note: on ne voit que Saisie.crea(z) à la ligne 87. Une fonction saisie_create(z) aurait aussi bien fait l'affaire.

    Par contre, vous fabriquez pleins d'"Entry" auxquelles vous associez un StringVar et des callbacks (OnValidate, ...).
    Voilà peut être un bon candidat pour construire une "class" qui regroupe tout çà.
    Qu'en pensez vous?

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

  6. #6
    Membre régulier
    Homme Profil pro
    retraité
    Inscrit en
    Septembre 2010
    Messages
    102
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : retraité
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Septembre 2010
    Messages : 102
    Points : 71
    Points
    71
    Par défaut
    Salut (tardif suite à un petit ennui de santé), Wiztricks, content de vous retrouver.

    Bien sûr que c'est la bonne question.
    J'ai vainement essayé de construire cette classe regroupant l'ensemble ce qui me parait plus logique mais je n'ai pas su traduire ma pensée en code

  7. #7
    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,

    Essayez de reprendre ce que je racontais ici.
    Je sais que c'est difficile mais je ne vois pas quelles sont les difficultés que vous rencontrez.

    Prenez soin de vous

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

Discussions similaires

  1. Modification de couleur des widgets
    Par awalter1 dans le forum GTK+ avec Python
    Réponses: 2
    Dernier message: 05/10/2007, 17h24
  2. Réponses: 5
    Dernier message: 18/07/2007, 18h11
  3. accrocher des widget sur une table
    Par insa59 dans le forum GTK+ avec C & C++
    Réponses: 6
    Dernier message: 02/04/2007, 11h32
  4. Exporter des widgets depuis une DLL
    Par zebiloute dans le forum wxWidgets
    Réponses: 5
    Dernier message: 31/07/2006, 08h14

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