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 :

Actualisation dynamique d'un paramètre de Menu tkinter. [Python 3.X]


Sujet :

Tkinter Python

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Enseignant
    Inscrit en
    Août 2019
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Nicaragua

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2019
    Messages : 56
    Points : 26
    Points
    26
    Par défaut Actualisation dynamique d'un paramètre de Menu tkinter.
    Bonjour

    Dans mon projet d'application en python, il y a 2 modes : le mode "Feuilletage" (le mode par défaut) et le mode "Édition". Pour passer de l'un à l'autre, on va dans le menu "Édition" et on choisit la ligne correspondante. (J'ajouterai peut-être un bouton de bascule après...)
    Je voudrais :
    --> en mode "Feuilletage", que seule la ligne "Mode édition" soit cliquable et "Mode feuilletage" soit désactivé (grisé).
    --> en mode "Édition", que seule la ligne "Mode feuilletage" soit cliquable et "Mode édition" soit désactivé (grisé).

    J'arrive à faire un affichage dynamique du texte d'un "Label" ou d'un "Button".
    Ça fonctionne bien. Cependant, le changement "dynamique" des valeurs de mes "StringVar" ne semblent pas affecter (dynamiquement) les paramètres du menu... Ils sont affectés au démarrage et puis c'est fini...

    J'ai réalisé un programme minimaliste pour isoler et résoudre le problème mais je ne trouve toujours pas la faille... Le voici :

    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
    # Essai de modification d'un paramère de menu
    import tkinter as tk
    root = tk.Tk()
    root.geometry("200x100")
     
    # Création des variables de contrôle édition / feuilletage (griser les menus
    a = tk.StringVar(master=root)
    b = tk.StringVar(master=root)
     
    # Création de la fenêtre contenant les informations
    bar_menu = tk.Menu(root)
    root.config(menu=bar_menu)
     
    # Fonctions activées par les menus
    def mode_feuil():              # Griser "Feuilletage" et activer "Édition"
        a.set("disabled")
        b.set("active")
     
    def mode_edit():               # Griser "Édition" et activer "Feuilletage"
        a.set("active")
        b.set("disabled")
     
    def menu():
        mode_feuil()
        # Menu "Fichier"
        fichier = tk.Menu(bar_menu, tearoff=0)
        fichier.add_command(label="Fermer", command=quit)
        bar_menu.add_cascade(label="Fichier", menu=fichier)
        # Menu "Edition"
        edition = tk.Menu(bar_menu, tearoff=0)
        edition.add_command(label="Mode feuilletage", command=mode_feuil, state=a.get())
        edition.add_command(label="Mode édition", command=mode_edit, state=b.get())
        bar_menu.add_cascade(label="Édition", menu=edition)
     
    label = tk.Label(root, textvariable=a)
    label.pack()
    bouton1 = tk.Button(root, textvariable=a, command=mode_feuil)
    bouton1.pack()
    bouton2 = tk.Button(root, textvariable=b, command=mode_edit)
    bouton2.pack()
     
    menu()
    mode_feuil()
     
    root.mainloop()
    Auriez-vous une idée de comment affecter dynamiquement le paramètre "state" d'un menu ?

    Merci à vous

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

    Citation Envoyé par Yobeco Voir le message
    Auriez-vous une idée de comment affecter dynamiquement le paramètre "state" d'un menu ?
    L'entrée d'un menu n'est pas un widget (d'ailleurs .add_command ne retourne rien).

    Par contre, les entrées sont indexées (le numéro de l'index suit l'ordre des ajouts) et il y a des méthodes pour modifier l'entrée à l'index n (.entryconfigure).

    - W

  3. #3
    Membre régulier
    Inscrit en
    Juillet 2013
    Messages
    80
    Détails du profil
    Informations forums :
    Inscription : Juillet 2013
    Messages : 80
    Points : 119
    Points
    119
    Par défaut
    Bonjour,

    Je ne suis pas certain de comprendre l'intérêt des stringvar dans cette situation... est-ce que ceci convient ?

    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
    # Essai de modification d'un paramère de menu
    import tkinter as tk
    root = tk.Tk()
    root.geometry("200x100")
     
    def mode_feuil():              # Griser "Feuilletage" et activer "Édition"
        b1.configure(state="disabled")
        b2.configure(state="active")
     
    def mode_edit():               # Griser "Édition" et activer "Feuilletage"
        b2.configure(state="disabled")
        b1.configure(state="active")
     
    # Creating buttons
    b1 = tk.Button(root, text='Feuilletage', command=mode_feuil)
    b2 = tk.Button(root, text='Edition', command=mode_edit)
     
    #Pack buttons
    b1.pack()
    b2.pack()
     
    # Default state
    mode_feuil()
     
    # Run !
    root.mainloop()

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 302
    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 302
    Points : 36 801
    Points
    36 801
    Par défaut
    Citation Envoyé par charliemtx Voir le message
    Je ne suis pas certain de comprendre l'intérêt des stringvar dans cette situation... est-ce que ceci convient ?
    Ca convient pour des Button (ou d'autres widgets).
    Ici le problème est de modifier les entrées d'un Menu.

    - W

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

    Après avoir eu/pris le temps de coder un exemple, çà donne un truc du genre:
    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 *
     
    labels = list('ABC')
     
    root=Tk()
     
    def do_reset():
        for i in range(len(labels)):
            menu.entryconfig(i+1,state=NORMAL)
     
    menu = Menu(root)
    for i, label in enumerate(labels, start=1):
        menu.add_command(label=label,
            command=lambda i=i: menu.entryconfig(i,state=DISABLED))
     
    menu.add_command(label="Reset", command=do_reset)
    menu.add_command(label="Exit", command=root.quit)
     
    root.config(menu=menu)
    root.mainloop()
    mais il y a d'autres possibilités...

    Et il faut prendre le temps de lire la documentation pour commencer à imaginer tout ce qu'on peut faire avec les Menu.

    - W

  6. #6
    Nouveau membre du Club
    Homme Profil pro
    Enseignant
    Inscrit en
    Août 2019
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Nicaragua

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2019
    Messages : 56
    Points : 26
    Points
    26
    Par défaut
    Merci à tous

    Comme d'habitude, Wiztricks, quand je lis un de tes codes, s'ouvre à moi une mine de concepts à découvrir et à digérer...
    Je vais m'y atteler dés que possible (les cours ayant repris, j'ai moins de temps libre maintenant. )

    Juste pour information : le bouton "Exit" ne fonctionne que si j'enlève root. dans command=root.quit

    De mon côté, j'avais élaboré ce code-ci (que je sais qualifiable de "naïf" ) :
    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
    import tkinter as tk
    root = tk.Tk()
    root.geometry("200x100")
     
    bar_menu = tk.Menu(root)
    root.config(menu=bar_menu)
     
    feuil = True       # Variable mémorisant le mode : Édition (feuil = False) ou Feuilletage (feuil = True)
     
    # Fonctions activées par les menus
    def bascul_mod(menu):
        global feuil                                           # Rendre la variable accessible
        if feuil == True:                                      # Selon le mode en cours, grise le menu correspondant
            index_1 = 1
            index_2 = 0
        else:
            index_1 = 0
            index_2 = 1
        menu.entryconfigure(index_1, state="disabled")         # Fixer l'état du paramètre "state=" dans l'entrée choisie du menu
        menu.entryconfigure(index_2, state="active")
        feuil = not feuil                                      # Basculer le booléen pour changer de mode
        affich_mod()                                           # Afficher le mode dans lequel on est
     
    def affich_mod():                                          # Fonction pour afficher le mode en cours
        global feuil
        if feuil == True:
            print('Mode "Feuilletage" activé')
        else:
            print('Mode "Édition" activé')
     
    # Création du menu
    def menu():
        global feuil
        global edition
        # Menu "Fichier"
        fichier = tk.Menu(bar_menu, tearoff=0)                 # Ne pas permettre au menu d'être décroché
        fichier.add_command(label="Fermer", command=quit)
        bar_menu.add_cascade(label="Fichier", menu=fichier)
     
        # Menu "Edition"
        edition = tk.Menu(bar_menu, tearoff=0)
        edition.add_command(label="Mode feuilletage", command=lambda: bascul_mod(edition), state="disable")     # ou "disabled"
        edition.add_command(label="Mode édition", command=lambda: bascul_mod(edition), state="active")
        print()
        bar_menu.add_cascade(label="Édition", menu=edition)
     
        affich_mod()
     
    menu()
     
    bout_basc = tk.Button(root, text="Changer de mode", command=lambda: bascul_mod(edition))
    bout_basc.pack()
     
    root.mainloop()
    Il a la qualité de fonctionner. Les menus et le bouton réagissent comme je le souhaite. Si vous avez des remarques... Je suis ouvert.

    Cependant, je n'ai pas encore réussi à utiliser la méthode .index() qui permet de déterminer, si j'ai bien compris, l'index de l'entrée d'un menu grâce à son label. (J'y reviendrai dés que possible)

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

    Citation Envoyé par Yobeco Voir le message
    Juste pour information : le bouton "Exit" ne fonctionne que si j'enlève root. dans command=root.quit
    "quit" force la sortie du programme.
    "root.quit" demande la sortie de mainloop.
    Ajoutez un print ('***') juste après l'appel à mainloop (la dernière ligne de votre code) et regardez la différence entre les deux.

    Au final les deux "fonctionnent" (différemment) et j'ai testé votre code, çà fait bien ce qu'on peut s'en attendre.

    Citation Envoyé par Yobeco Voir le message
    Cependant, je n'ai pas encore réussi à utiliser la méthode .index() qui permet de déterminer, si j'ai bien compris, l'index de l'entrée d'un menu grâce à son label. (J'y reviendrai dés que possible)
    Si je reprends mon code pour y ajouter un test de .index:
    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
    from tkinter import *
     
    labels = list('ABC')
     
    root=Tk()
     
    def do_reset():
        for i in range(len(labels)):
            menu.entryconfig(i+1,state=NORMAL)
     
    def do_showindex():
        for s in labels:
            print(s, menu.index(s))
     
    menu = Menu(root)
    for i, label in enumerate(labels, start=1):
        menu.add_command(label=label,
            command=lambda i=i: menu.entryconfig(i,state=DISABLED))
     
    menu.add_command(label="Show index", command=do_showindex)
    menu.add_command(label="Reset", command=do_reset)
    menu.add_command(label="Exit", command=root.quit)
     
    root.config(menu=menu)
    root.mainloop()
    Il fait ce que j'attends.

    Citation Envoyé par Yobeco Voir le message
    Si vous avez des remarques... Je suis ouvert.
    Vous faites avec le Python/tkinter que vous connaissez et vous savez que vos connaissances sont "limités" (ce qui réduit ce que vous pouvez exprimer en code - comme vous seriez limité pour exprimer des choses dans une langue inconnue).

    On essaie de se mettre à votre niveau et de ne pas taper...

    Quelques trucs:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    def affich_mod():                                          # Fonction pour afficher le mode en cours
        global feuil
        if feuil == True:
            print('Mode "Feuilletage" activé')
        else:
            print('Mode "Édition" activé')
    Si vous aviez eu le courage d'appeler votre fonction afficher_mode est ce que le commentaire aurait encore quelque utilité?

    le mot clef global n'est utile que dans les fonctions qui vont assigner un objet à la variable correspondante. Ici on lit feuil (variable globale) mais on ne lui assigne rien: "global" n'est pas utile.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
        edition.add_command(label="Mode feuilletage", command=lambda: bascul_mod(edition), state="disable")     # ou "disabled"
    Si vous ne voulez pas vous tromper, faites un import de tkinter.constants: il va définir la variable DISABLED et vous forcer à utiliser le même symbole partout (sinon çà va râler qu'il n'est pas défini) plutôt que de profiter des largesses de tkinter qui va accepter plusieurs chaines de caractères...

    C'est vous qui voyez.

    - W

  8. #8
    Nouveau membre du Club
    Homme Profil pro
    Enseignant
    Inscrit en
    Août 2019
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Nicaragua

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2019
    Messages : 56
    Points : 26
    Points
    26
    Par défaut
    Si je reprends mon code pour y ajouter un test de .index:
    Merci beaucoup pour le temps consacré.
    Je vais l'étudier.

    On essaie de se mettre à votre niveau et de ne pas taper...

    Étant professeur moi-même, de nombreuses situations au quotidien me permettent de comprendre ce que vous pouvez ressentir. Ça me donne la force d'être patient à mon tour.
    Voici un article Wikipedia sur l'effet Dunning-Kruger qui peut aider à comprendre les relations entre les gens présentant de écarts de compétences. Moi, je pense être tout au fond de la vallée de l'humilité (quoique je ne me rappelle pas être passé par le sommet) quand vous, vous êtes probablement sur le plateau de la consolidation :-)

    Si vous aviez eu le courage d'appeler votre fonction afficher_mode est ce que le commentaire aurait encore quelque utilité?
    J'avais utilisé une notation plus courte au début (d'où le commentaire) mais je l'ai changée par la suite sans réactualiser / effacer ce commentaire correspondant. D'où l'effet comique de la redondance au final...

    le mot clef global n'est utile que dans les fonctions qui vont assigner un objet à la variable correspondante. Ici on lit feuil (variable globale) mais on ne lui assigne rien: "global" n'est pas utile.
    Je crois que dans une ancienne version, j'utilisais la variable "feuil" dans cette fonction et j'ai oublié d'actualiser...
    En fait quand vous, vous planifiez mentalement en amont, avant de vous mettre au clavier, moi je tâtonne énormément, je découvre et applique ce que je crois avoir compris, notion après notion... Ce qui amène (pour la seconde fois) à une actualisation incomplète de mon code... Je me rends compte qu'il faut que je sois plus vigilent sur ce point...

    Si vous ne voulez pas vous tromper, faites un import de tkinter.constants: il va définir la variable DISABLED et vous forcer à utiliser le même symbole partout (sinon çà va râler qu'il n'est pas défini plutôt que de profiter des largesses de tkinter qui va accepter plusieurs chaines de caractères...
    Après quelques investigations et essais-erreurs, j'ai compris qu'avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    from tkinter.constants import *
    je pouvais, par la suite, utiliser les valeurs DISABLED et ACTIVED pour le paramètre state= au lieu des équivalents en string.
    Je vais me documenter pour voir quels autres avantages confèrent .constants
    Cependant, en quoi est-ce mieux d'utiliser les constantes en majuscules plutôt que les string ? En quoi lire des chaînes de caractères est une "largesse" de tkinter ?
    J'avais effectivement déjà remarqué que des codes utilisaient une notation, et d'autres codes, l'autre notation.

    Il y a un autre point formel sur lequel je commence également à sentir mes limites : plus le code de mon projet principal grandit, plus il me semble désordonné, difficile à relire... (D'où mes nombreux commentaires...)
    En C Arduino, c'était très simple à organiser :
    - Ma première partie correspondait à la boucle principale.
    - En dessous, je définissais toutes les fonctions que j'allais utiliser.
    L'ordre des fonctions n'avait aucune importance : tout était compilé avant exécution.

    Mais, sauf erreur de ma part, le Python est interprété ce qui signifie que chaque fonction doit être définie avant d’être appelée.
    Cela fait une contrainte en plus pour structurer mon code...

    Y a-t-il des manières plus efficaces que d'autres pour organiser son code ? (Peut-être faudra-t-il ouvrir un autre sujet pour ce thème...)

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

    Citation Envoyé par Yobeco Voir le message
    Moi, je pense être tout au fond de la vallée de l'humilité (quoique je ne me rappelle pas être passé par le sommet) quand vous, vous êtes probablement sur le plateau de la consolidation :-)
    mouais... et arrivé là haut on peut apprécier l'étendue de son ignorance.

    Citation Envoyé par Yobeco Voir le message
    J'avais utilisé une notation plus courte au début (d'où le commentaire) mais je l'ai changée par la suite sans réactualiser / effacer ce commentaire correspondant. D'où l'effet comique de la redondance au final...
    Je sais pas. Je dirais que quand un élève rend une copie de devoir de maths, on attend à ce qu'il se soit un peu appliqué sur la forme. Ce n'est pas une critique: juste que demander qu'on lise son code, c'est que vous y avez mis le meilleur de vous même. Donc quand on lit, on se demande si le concept a été compris.

    Citation Envoyé par Yobeco Voir le message
    Cependant, en quoi est-ce mieux d'utiliser les constantes en majuscules plutôt que les string ? En quoi lire des chaînes de caractères est une "largesse" de tkinter ?
    Ca dépend.
    Si j'écris DISABELD au lieu de DISABLED çà va sortir un NameError avant d'essayer d'exécuter l'instruction. Avec une chaine de caractères "disabeld" çà marchera, fera n'importe quoi, sortira une erreur.
    Pour moi, c'est juste une astuce pour gérer des fautes de frappes.


    Citation Envoyé par Yobeco Voir le message
    L'ordre des fonctions n'avait aucune importance : tout était compilé avant exécution.

    Mais, sauf erreur de ma part, le Python est interprété ce qui signifie que chaque fonction doit être définie avant d’être appelée.
    Cela fait une contrainte en plus pour structurer mon code...
    En fait, Python est "compilé" mais çà n'apporte rien à cela.
    Je peux fabriquer une fonction qui appelle une fonction pas encore définie.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    >>> def f():
    ...     g()
    ...
    >>> g
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    NameError: name 'g' is not defined
    >>>
    Et en fait quand on définit une fonction f, on crée une variable globale f associée à un objet fonction (du code compilé).
    Pourvu que la variable globale g soit créée avant l'appel de la fonction, Python saura que faire lorsqu'il rencontre ce g.

    Revisitez les dictionnaires.
    Une variable est une association clef/valeurs dans un dictionnaire globals() propre au module courant. Tant que je trouve la clef pour récupérer la valeur associée, çà roule.

    Citation Envoyé par Yobeco Voir le message
    Y a-t-il des manières plus efficaces que d'autres pour organiser son code ? (Peut-être faudra-t-il ouvrir un autre sujet pour ce thème...)
    Les méthodes les plus conventionnelles seront de regrouper les fonctions en class (la POO) ou en modules séparés (ce qui est une version light de la chose).

    Dans les deux cas, c'est compliqué parce qu'on passe d'un truc "plat" à une structure hiérarchique voire arborescente. Et qu'en rangeant son code dans des boîtes, il va falloir créer des ouvertures (interface) pour que çà communique.

    Faire vos premiers pas sera facile et programmer avec tkinter est une bonne occasion pour voir des domaines d'application de ces choses là. Pour le reste, il y a de la littérature, des tas d'écoles,...

    - W

  10. #10
    Nouveau membre du Club
    Homme Profil pro
    Enseignant
    Inscrit en
    Août 2019
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Nicaragua

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2019
    Messages : 56
    Points : 26
    Points
    26
    Par défaut
    Je sais pas. Je dirais que quand un élève rend une copie de devoir de maths, on attend à ce qu'il se soit un peu appliqué sur la forme. Ce n'est pas une critique: juste que demander qu'on lise son code, c'est que vous y avez mis le meilleur de vous même. Donc quand on lit, on se demande si le concept a été compris.
    Tout à fait... Désolé...

    Avec une chaîne de caractères "disabeld" çà marchera, fera n'importe quoi, sortira une erreur.
    Je comprends... Mais c'est très surprenant pour moi.
    Juste un détail : dans votre exemple de code précédent, vous avez utilisé la notation des variables DISABLED en majuscules sans avoir utilisé :
    from tkinter.constants import *
    C'est possible parce que vous avez utilisé : from tkinter import * au lieu de import tkinter as tk . C'est bien ça ?

    Les méthodes les plus conventionnelles seront de regrouper les fonctions en class (la POO) ou en modules séparés (ce qui est une version light de la chose).
    Je vais me renseigner là dessus...

    Voici maintenant les résultats de mon analyse des index des menus à l'aide de la méthode .index()
    C'est surtout pour les futurs lecteurs de ce sujet.

    Voici mon code d'essai :
    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
    # Code d'essai proposé par wiztricks pour comprendre la methode ".index()" (et l'activation / désactivation d'un menu)
    # Commenté par Yobeco pour s'aider à comprendre les notions utilisées
    # Ajout également de sous-menus (entrées) pour étudier les index de ces sous-menus
     
    from tkinter import *
     
    labels = list('ABCD')       # Création d'une liste à partir d'une "String" pour créer des boutons par la suite
     
    root=Tk()
    root.geometry("400x100")    # Fixer une taille à la fenêtre pour que tous les menus créés puissent loger.
     
    #########################################################
    #    Création des fonctions activées par les menus      #
    #########################################################
     
    # Fonction pour réactiver les menus 'ABCD'
    def do_reset():
        for i in range(len(labels)):                 # range(len(labels)) crée une liste composée d'une suite de "int" de la taille de la liste "labels" --> http://www.imarend.com/tutorials/PythonBase/python10FR.html
            menu.entryconfig(i+1,state=NORMAL)       # Pour chaque menu d'index correspondant à ces valeurs, imposer l'état NORMAL (cliquable)
                                                     # "i+1" On commence à 1 parce que le premier menu (à gauche) est indexé à 1 par défaut
     
    # Fonction pour afficher l'index des menus 'ABCD'
    def do_showindex():
        for s in labels:                                      # Pour troutes les valeurs des cellules de la liste "labels" (labels de menus donc)
            print("L'index de", s, "est", menu.index(s))      # Afficher le label du menu et l'index correspondant
     
    ##############################
    #    Création des menus      #
    ##############################
     
    menu = Menu(root)                               # Création du menu dans la fenêtre root
     
    # Créations de menus 'ABCD' directement actifs dans la barre de menu (façon boutons)
    # Documentation sur "enumerate()" --> https://docs.python.org/fr/3/library/functions.html#enumerate
    for i, label in enumerate(labels, start=1):     # Pour chaque élément de la liste "labels" en obligeant le premier éléménent à avoir l'index 1 --> "start=1"
                                                    # (parce que le premier élément du menu (à gauche) a, par définition, l'index 1)
        menu.add_command(label=label,               # --> créer un menu ayant l'élément de la liste "labels" comme texte
            # et une fonction qui permet de désactiver le menu quand il est cliqué
            command=lambda i=i: menu.entryconfig(i,state=DISABLED))     # Dans "lambda" : "i=i" oblige "i" de "lambda" à être le même que le "i" de la boucle "for"
            # Ainsi, la fonction de chaque bouton est de se désactiver
     
    # Affichage des autres boutons
    menu.add_command(label="Show index", command=do_showindex)
    menu.add_command(label="Reset", command=do_reset)
    menu.add_command(label="Exit", command=root.quit)
     
    # Création d'un menu dépliable pour étudier les index des entrées (sous-menus)
    menu_depl = Menu(menu, tearoff=0)                 # tearoff=0 interdit au menu dépliable d'être décroché de la fenêtre
     
    # --> 1er code (naïf) : il correspond explicitement à l'idée que je voulais mettre en place :
    # menu_depl.add_command(label="Entrée 0", command=lambda: print('L\'index de "Entrée 0" est :', menu_depl.index("Entrée 0")))
    # menu_depl.add_command(label="Entrée 1", command=lambda: print('L\'index de "Entrée 1" est :', menu_depl.index("Entrée 1")))
    # menu_depl.add_command(label="Entrée 2", command=lambda: print('L\'index de "Entrée 2" est :', menu_depl.index("Entrée 2")))
    # menu_depl.add_command(label="Entrée 3" ...
     
    # --> 2ème code plus efficace pour produire le même résultat :
    for i in range(7):
        label_i = "Entrée " + str(i+1)             # Préparer un label pour chaque sous-menu en utilisant "i"
        menu_depl.add_command(label=label_i,       # Création des sous-menus
                              command=lambda label_i=label_i: print('L\'index de', label_i, 'est :', menu_depl.index(label_i)))
        # Dans "lambda", "label_i=label_i" permet à la variable "label_i" d'être la même que dans la boucle "for"
        # Ainsi, à chaque appel de "lambda", chaque entrée renvoie bien son index
        # Dans "menu_depl.index(label_i)" : c'est parce quon applique la méthode .index() à "menu_depl" qu'on obtient les index des entrées du menu dépliant
    menu.add_cascade(label="Menu dépliable", menu=menu_depl)     # Afficher le menu en cascade
     
    # Afficher les index de chaque menu
    print('L\'index de "Show index" est :', menu.index("Show index"))
    print('L\'index de "Reset" est :', menu.index("Reset"))
    print('L\'index de "Exit" est :', menu.index("Exit"))
    print('L\'index de "Menu dépliable" est :', menu.index("Menu dépliable"))
     
    root.config(menu=menu)
    root.mainloop()
    Et voici une illustration de ma compréhension de l'indexage des menus :

    Nom : Index des menus et sous-menus.jpg
Affichages : 1188
Taille : 24,4 Ko

    Si ça peut aider quelqu'un...

    J'imagine que cette doc existait déjà, mais j'aime la citation préférée de "fred1599" :
    "La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information. Einstein "

    Merci encore à vous :-)
    De mon côté, me voici capable de repérer un menu ou un sous-menu par son index pour l'activer ou le désactiver, le mystère est donc élucidé.

    J'attends un peu vos remarques avant de cliquer sur le bouton "Résolu".

  11. #11
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 302
    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 302
    Points : 36 801
    Points
    36 801
    Par défaut
    Citation Envoyé par Yobeco Voir le message
    C'est possible parce que vous avez utilisé : from tkinter import * au lieu de import tkinter as tk . C'est bien ça ?
    Yes.

    Citation Envoyé par Yobeco Voir le message
    J'imagine que cette doc existait déjà, mais "fred1599" aime à citer Einstein :
    "La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information."
    Je dirais que çà ne sert à rien... sauf à vous permettre de mettre vos idées au clair (et c'est déjà pas si mal).
    En gros, ceux qui voudront emprunter ce même chemin devront y mettre la même énergie pour voir comment çà marche et l'adapter à leur besoin.
    Votre boulot dit juste que c'est possible.
    C'est déjà pas si mal...ça rassure un peu mais ils devront quand même ramer pour s'approprier tout çà.

    Après côté citation, je préfère:
    La vraie connaissance est de connaître l'étendue de son ignorance.
    Confucius

    Je la trouve bien plus adaptée au domaine de l'informatique. Car plus que partout ailleurs, il faut y apprendre à gérer son ignorance.

    - W

  12. #12
    Nouveau membre du Club
    Homme Profil pro
    Enseignant
    Inscrit en
    Août 2019
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Nicaragua

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2019
    Messages : 56
    Points : 26
    Points
    26
    Par défaut
    Oui, je comprends.

    Merci pour les conseils et pour le temps consacré !

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

Discussions similaires

  1. Passer une variable de classe en paramètre d'un menu
    Par Xaziou dans le forum Composants graphiques
    Réponses: 4
    Dernier message: 11/05/2011, 16h30
  2. Passage paramètres Grid et Menu
    Par sbernard dans le forum Ext JS / Sencha
    Réponses: 3
    Dernier message: 23/06/2010, 10h56
  3. [2K5] Actualisation liste avec paramètre NULL
    Par Lolomenfin dans le forum SSRS
    Réponses: 1
    Dernier message: 28/02/2009, 11h36
  4. Menu Tkinter avec lien dans label d'un sous-menu
    Par quentinlecler dans le forum Tkinter
    Réponses: 4
    Dernier message: 09/07/2008, 09h51
  5. problème menu Tkinter
    Par pedro99 dans le forum Tkinter
    Réponses: 1
    Dernier message: 06/11/2007, 20h09

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