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 :

créer des boutons dans une boucle for


Sujet :

Tkinter Python

  1. #1
    Membre à l'essai
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2016
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Novembre 2016
    Messages : 25
    Points : 12
    Points
    12
    Par défaut créer des boutons dans une boucle for
    Bonjour,
    Je souhaiterai utiliser une boucle pour créer un nombre déterminé de boutons qui appellent respectivement une fonction. Pour celà j'ai écris le code suivant
    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
    import tkinter as tk
    import numpy as np
     
    fenetre = Tk()
    fenetre.title("Calcul de réflectivité")
     
    def test():
     
        truc = float(couche.get())+1
        nb_couche = round(truc)
        a = np.zeros(shape=(nb_couche-1,2))
        #print(a)
     
     
        for i in range(1,nb_couche):
            position_ligne=i+5
            global biz
            biz="bou"+str(i) #on appelle les boutons bou1, bou2,...boui
            print(biz)
     
         # Création du bouton matériau
     
            biz = Button(fenetre, text="materiau n°" +str(i),command = lambda i=i : fonction(i))
    #        biz = Button(fenetre, text="materiau n°" +str(i),command = fonction)
            biz.grid(row=position_ligne, column=0,sticky=E, padx=5, pady=5)
    #        bout1 = Button(fenetre, text='test',command = nb_couche)
    #        bout1.grid(row=bat, column=0,sticky=E, padx=5, pady=5)
     
            # Création du texte 'épaisseur'
     
            epaiss=Entry(textvariable=thick,width=5,bg ='bisque', fg='maroon')
            epaiss.grid(row=position_ligne, column=2,sticky=W, padx=5, pady=5)
     
            Label6 = Label(fenetre, text = "thickness n°" +str(i))
            Label6.grid(row=position_ligne, column=1,sticky=E, padx=5, pady=5)
     
            # Création du texte 'indice'
     
            indice=Entry(textvariable="",width=5,bg ='bisque', fg='maroon')
            indice.grid(row=position_ligne, column=4,sticky=W, padx=5, pady=5)
     
            Label4 = Label(fenetre, text = "indice n°" +str(i))
            Label4.grid(row=position_ligne, column=3,sticky=E, padx=5, pady=5)
     
            # Création du texte 'coeff extinction'
     
            imagi=Entry(textvariable="",width=5,bg ='bisque', fg='maroon')
            imagi.grid(row=position_ligne, column=6,sticky=W, padx=5, pady=5)
     
            Label5 = Label(fenetre, text = "extinction n°" +str(i))
            Label5.grid(row=position_ligne, column=5,sticky=E, padx=5, pady=5)
     
    def fonction(num):
     
        if bou[num].get()==1:
            print("ok")
     
    thick=StringVar()
    ncouche=StringVar()
     
    bout = Button(fenetre, text='OK',command = test)
    bout.grid(row=4, column=2,sticky=EW, padx=5, pady=5)
     
    couche=Entry(textvariable=ncouche,width=5,bg ='bisque', fg='maroon')
    couche.grid(row=4, column=1,sticky=W, padx=5, pady=5)
     
    Label3 = Label(fenetre, text = "couche(s) ")
    Label3.grid(row=4, column=0,sticky=E, padx=5, pady=5)
     
    fenetre.mainloop()
    Le principe est que lorsque je rentre un nombre N de couches, le code me crée N boutons dans mon interface tkinter nommés de 1 à N. Mon objectif est que lorsque je clique sur un bouton, il appelle une fonction qui me remplisse les champs vide se trouvant sur la même ligne que le bouton. Par exemple, si je clique sur le premier bouton "matériau" se trouvant à la ligne 6, il remplisse les champs de la ligne 6 et ainsi de suite pour les N boutons "matériau" créés. Il faudrait que la commande du bouton ainsi que la fonction associée dépendent de "i" mais je ne vois pas comment l'écrire. Merci

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

    Un truc comme çà peut être?

    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
    import tkinter as tk
     
    labels = []
     
    def do_update(i):
        for j, label in enumerate(labels[i:], start=i):
            label.configure(text='u %d' % j)
     
    for i in range(10):
        btn = tk.Button(text='b %d' % i, command=lambda i=i: do_update(i))
        btn.grid(row=i, column=0)
        label = tk.Label(text='')
        label.grid(row=i, column=1)
        labels.append(label)
     
    tk.mainloop()
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre à l'essai
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2016
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Novembre 2016
    Messages : 25
    Points : 12
    Points
    12
    Par défaut
    Merci wiztricks pour votre aide. C'est en effet ce que je cherche à faire. Je ne pense pas que je dois utiliser la fonction "enumerate" dans mon cas vu que je souhaite en quelque sorte afficher "u0" lorsque je clique sur "b0"; "u1" quand je clique sur "b1" etc. Je vais adapter cela à mon code et je vous tiens au courant.

  4. #4
    Membre à l'essai
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2016
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Novembre 2016
    Messages : 25
    Points : 12
    Points
    12
    Par défaut
    Rebonjour,

    J'arrive maintenant à afficher du texte à droite de mes boutons.
    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
    import tkinter as tk
    import numpy as np
     
    fenetre = Tk()
    fenetre.title("Calcul de réflectivité")
     
     
    def fonction(num):
        for j in range(num+1):
            posi = num+5
            label = Label(fenetre, text='')
            label.configure(text="indice"+str(j))
            label.grid(row=posi, column=1)
     
     
    def test():
     
        truc = float(couche.get())+1
        nb_couche = round(truc)
     
        for i in range(1,nb_couche):
     
            position_ligne=i+5
     
           # Création du bouton matériau
     
            biz = Button(fenetre, text="materiau n°" +str(i),command = lambda i=i : fonction(i))
            biz.grid(row=position_ligne, column=0,sticky=E, padx=5, pady=5)
     
     
            # Création du texte 'coeff extinction'
     
            imagi=Entry(textvariable="",width=5,bg ='bisque', fg='maroon')
            imagi.grid(row=position_ligne, column=6,sticky=W, padx=5, pady=5)
     
            Label5 = Label(fenetre, text = "extinction n°" +str(i))
            Label5.grid(row=position_ligne, column=5,sticky=E, padx=5, pady=5)
     
    ncouche=StringVar()
     
    bout = Button(fenetre, text='OK',command = test)
    bout.grid(row=4, column=2,sticky=EW, padx=5, pady=5)
     
    couche=Entry(textvariable=ncouche,width=5,bg ='bisque', fg='maroon')
    couche.grid(row=4, column=1,sticky=W, padx=5, pady=5)
     
    Label3 = Label(fenetre, text = "couche(s) ")
    Label3.grid(row=4, column=0,sticky=E, padx=5, pady=5)
     
    fenetre.mainloop()
    Désormais quand j'appuie sur le bouton "matériau 1" par exemple, j'ai le texte "indice 1" qui s'affiche à coté. Mon objectif est maintenant d'afficher ce texte quand je clique sur mon bouton non pas à coté du bouton mais dans une zone de texte variable. Je souhaite réaliser cela car j'aimerai avoir le choix de remplir le champ "textvariable" manuellement ou en appuyant sur un bouton "matériau". Le problème avec textvariable c'est que je n'arrive pas à afficher du texte dans le champ de texte variable quand je clique sur mon bouton mais je peux le rentrer manuellement. Est ce que vous connaissez une fonction qui me permette de faire les deux ? Merci

  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
    Citation Envoyé par jaky33 Voir le message
    Le problème avec textvariable c'est que je n'arrive pas à afficher du texte dans le champ de texte variable quand je clique sur mon bouton mais je peux le rentrer manuellement. Est ce que vous connaissez une fonction qui me permette de faire les deux ?
    Il suffit d'associer aux widgets une variable tkinter (qui est différente d'une variable Python) et de la modifier. Et commencer par des exemples simples:
    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
    import tkinter as tk
     
    root = tk.Tk()
    variable = tk.StringVar()
    variable.set('count = 0')
    count = 0
    def do_click():
        global count
        count += 1
        variable.set('count = %d' % count)
     
    tk.Button(root, text='click', command=do_click).grid(row=0, column=0)
    tk.Label(root, textvariable=variable).grid(row=0, column=1)
    tk.Entry(root, textvariable=variable).grid(row=0, column=2)
    tk.mainloop()
    Une variable, 3 widgets et on essaie de voir si on comprend comment le mettre en œuvre.

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

  6. #6
    Membre à l'essai
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2016
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Novembre 2016
    Messages : 25
    Points : 12
    Points
    12
    Par défaut
    Bonjour,
    Merci Wiztricks pour votre réponse. J'arrive désormais à afficher du texte à l'intérieur des champs variables. Quand je crée N couches, cela me crée également N champs variables et N boutons.
    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
    import tkinter as tk
    from tkinter import *
    from tkinter import filedialog
     
    fenetre = Tk()
    fenetre.title("Calcul de réflectivité")
    variable = StringVar()
    variable.set(' ')
    ncouche=StringVar()
     
    def fonction(num):
        for j in range(num+1):
            variable.set("indice"+str(j)) 
     
     
    def test():
     
        truc = float(couche.get())+1
        nb_couche = round(truc)
     
     
        for i in range(1,nb_couche):
     
            position_ligne=i+5
     
     
           # Création du bouton matériau
     
            biz = Button(fenetre, text="materiau n°" +str(i),command = lambda i=i : fonction(i))
            biz.grid(row=position_ligne, column=0,sticky=E, padx=5, pady=5)
     
            bat=Entry(fenetre, textvariable=variable,width=5,bg ='bisque', fg='maroon').grid(row=position_ligne, column=2)
     
     
    bout = Button(fenetre, text='OK',width=5,command = test)
    bout.grid(row=4, column=2,sticky=EW, padx=5, pady=5)
     
    couche=Entry(textvariable=ncouche,width=5,bg ='bisque', fg='maroon')
    couche.grid(row=4, column=1,sticky=W, padx=5, pady=5)
     
    Label3 = Label(fenetre, text = "couche(s) ")
    Label3.grid(row=4, column=0,sticky=E, padx=5, pady=5)
     
    bout = Button(fenetre, text='OK',width=9,command = test)
    bout.grid(row=4, column=2,sticky=EW, padx=5, pady=5)
     
     
    tk.mainloop()
    Cependant je n'arrive pas à faire dépendre ces champs variables de "i". C'est à dire que lorsque je clique sur un bouton matériau, cela rempli les champs variables de toute la colonne. Ce que j'aimerai réussir à faire c'est de remplir uniquement le champ variable qui se trouve sur la même ligne que le bouton. Autrement dit il faudrait que mes N champs variables créés soient indépendant les uns des autres mais réalisent la même fonction. C'est à dire que lorsque je sélectionne "matériau 1", cela affiche "indice 1" dans le champ situé sur la meme ligne que le bouton puis quand je clique sur le bouton "matériau 2", cela affiche "indice 2" et ainsi de suite. J'arrive à faire cela avec des zones de texte en changeant cette partie du code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    def fonction(num):
        for j in range(num+1):
            posi = num+5
            label = Label(fenetre, text='')
            label.configure(text="indice"+str(j))
            label.grid(row=posi, column=1)
    mais pas avec des zones de texte variable.
    Merci

  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,

    Citation Envoyé par jaky33 Voir le message
    C'est à dire que lorsque je clique sur un bouton matériau, cela rempli les champs variables de toute la colonne. Ce que j'aimerai réussir à faire c'est de remplir uniquement le champ variable qui se trouve sur la même ligne que le bouton.
    C'est normal puisque vous avez associé la même variable à tous les widgets.
    Relisez mon premier exemple, si çà peut modifier les labels supérieurs à "j", c'est que j'ai pris la précaution de fabriquer une liste de Label et une correspondance (implicite) entre l'ordre de cette liste et leur emplacement dans la grille.
    Après, modifier directement le Label (ou l'Entry) ou la variable associée, çà va être pareil: une liste qui permette de récupérer l'index de la variable pour la modifier en fonction du ième Button sur lequel on appuie.
    Le deuxième exemple est juste la pour montrer qu'on peut associer une même variable à plusieurs widgets et qu'il faut modifier la variable pour que le contenu (qu'ils affichent) change.
    note: il existe une solution purement TCL/Tk permettant de récupérer le n° de ligne/colonne du widget sur lequel on a cliqué... Mais faire çà avec des listes c'est bien plus simple que de se prendre le chou à comprendre comment fonctionne cela côté Tk.

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

  8. #8
    Membre à l'essai
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2016
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Novembre 2016
    Messages : 25
    Points : 12
    Points
    12
    Par défaut
    Bonjour,
    Je vous remercie pour votre réponse. J'arrive à faire varier le texte d'un des widgets mais je ne parviens pas à créer cette dépendance entre la i ème variable et le i ème bouton. C'est à dire que lorsque j'appuie sur mon bouton matériau cela m'affiche bien l'indice correspondant mais pas au bon endroit. Dans votre exemple, j'arrive à afficher la correspondance u0 quand on appuie sur b0, u5 quand on appuie sur u5 etc mais pas avec la fonction enumerate.
    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
    import tkinter as tk
     
    labels = []
     
    def do_update(i):
        #for j, label in enumerate(labels[i:], start=i):
        for j in range (i+1):
            label.configure(text='u %d'%j)
            label.grid(row=j,column=1)
     
    for i in range(10):
        btn = tk.Button(text='b %d' % i, command=lambda i=i: do_update(i))
        btn.grid(row=i, column=0)
        label = tk.Label(text='')
        #label.grid(row=i, column=1)
        labels.append(label)
     
    tk.mainloop()

  9. #9
    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
    Beurk, c'est quoi ce 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
    import tkinter as tk
     
    labels = []
     
    def do_update(i):
        #for j, label in enumerate(labels[i:], start=i):
        for j in range (i+1):
            label.configure(text='u %d'%j)
            label.grid(row=j,column=1)
     
    for i in range(10):
        btn = tk.Button(text='b %d' % i, command=lambda i=i: do_update(i))
        btn.grid(row=i, column=0)
        label = tk.Label(text='')
        #label.grid(row=i, column=1)
        labels.append(label)
     
    tk.mainloop()
    Dans do_update, d'où sort "label"? C'est une variable globale et elle est associée au dernier Label créé dans la boucle "for" (ligne 10). Dans la boucle qui va de 0 à "i" inclus, vous modifiez ce label là puis vous le placez dans la ligne correspondante à "j". A la sortie, vous ne voyez pas les étapes intermédiaires, seulement l'affichage à la i-ème ligne.

    Une version plus concise de ce que fait votre do_update se résume à:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    def do_update(i):
            labels[i].configure(text='u %d'%i)
    A la différence que je modifie le i-ème Label (en le récupérant dans la liste "labels" qui sert justement à faire la correspondance entre les deux) et non le dernier que je balade ensuite.

    Si vous voulez travailler avec un ensemble/une collection de Labels, il faut connaître liste, dictionnaires, ... tous ces objets qui permettent de gérer des collections sans trop se prendre la tête. Si vous ne les maîtrisez pas, difficile de penser "avec"... et de s'en sortir pour ranger un tas de widgets.
    Alors ouvrez votre tuto. préféré et revoyez un peu tout çà.

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

Discussions similaires

  1. Créer et récupérer des variables dans une boucle for
    Par miou123 dans le forum Shell et commandes GNU
    Réponses: 6
    Dernier message: 09/06/2016, 19h20
  2. créer des Jlabel dans une boucle
    Par ballantine's dans le forum Débuter
    Réponses: 11
    Dernier message: 18/01/2010, 13h20
  3. declarer des functions de boutons dans une boucle for
    Par superleon dans le forum ActionScript 3
    Réponses: 1
    Dernier message: 06/06/2009, 12h24
  4. [E-07] créer des variables dans une boucle ?
    Par edouardg dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 02/12/2008, 22h19

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