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

Python Discussion :

Tkinter : créer un menu en fonction d'une liste [Python 3.X]


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    débutant
    Inscrit en
    Septembre 2017
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : débutant
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Septembre 2017
    Messages : 12
    Par défaut Tkinter : créer un menu en fonction d'une liste
    Bonjour,

    Je reprends l'apprentissage de Python depuis un moment et je me suis dit, rien de tel qu'un programme perso pour que ça rentre. Bref. Mon pseudo programme consiste à afficher des exercices de musculation, comprenant un texte descriptif et une image. Je souhaite accéder à ces exercices depuis un menu déroulant, pour ça j'utilise le module Tkinter.

    Seulement voilà : Mes exercices sont regroupés par catégories (Exercices A, exercices B, etc.) et stockés dans des dictionnaires. 1 dictionnaire pour les textes, 1 dictionnaire pour les images. J'ai aussi créé une liste de dictionnaires pour simplifier le code, avec un libellé, un texte et une image à chaque fois, mais cela complexifie encore plus la tâche et je ne suis pas assez à l'aise pour procéder de la sorte.

    Mon problème principal étant le suivant :

    En bon amateur que je suis, j'ai créé mon menu "Exercices" de sorte à ce que chaque commande pointe vers 1 exercice. Sachant qu'il y en a 65 environs, vous voyez un peu le tableau... Je sais que je peux utiliser une boucle pour simplifier mon code et ne pas avoir à taper une ligne de code par exercice, mais je n'arrive pas, malgré de nombreux tests sur l'interpréteur, à trouver une solution qui fonctionne.

    Voici mon code, j'y ai intégré au début mes dictionnaires (légèrement raccourcis bien sûr) :

    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
    from tkinter import *
    from tkinter import messagebox
    from tkinter.filedialog import askopenfilename
    from dicos_exercices import *
     
    dic_txt = {
        'exA': "EXERCICE A - Pectoraux, épaules, triceps\n\n"
        "blablabla", 
     
        'exA1': "EXERCICE A1 - Pectoraux, épaules, triceps\n\n"
        "blabliblou."
    }
     
    dic_img = {
        'imgA': 'images/imgA.gif', 'imgA1': 'images/imgA1.gif', 'imgA2': 'images/imgA2.gif',
        'imgA3': 'images/imgA3.gif', 'imgA456': 'images/imgA456.gif',
        'imgA7': 'images/imgA7.gif'
    }
     
    # Fenêtre principale
    class MyWindow(Tk):
     
        def __init__(self):
            Tk.__init__(self)
            self.createMenuBar()
     
            self.title( "Programme Lafay V1.0" )
     
        def createMenuBar(self):
            menuBar = Menu(self)
     
            menuFile = Menu(menuBar, tearoff = 0)
            menuFile.add_command(label = "Nouveau", command = None)
            menuFile.add_command(label = "Ouvrir", command = self.openFile)
            menuFile.add_command(label = "Sauvegarder", command = None)
            menuFile.add_separator()
            menuFile.add_command(label = "Exit", command = self.quit)
            menuBar.add_cascade( label = "Fichier", menu = menuFile)
     
            menuEdit = Menu(menuBar, tearoff = 0)
            menuEdit.add_command(label = "Annuler", command = None)
            menuEdit.add_separator()
            menuEdit.add_command(label = "Copier", command = None)
            menuEdit.add_command(label = "Couper", command = None)
            menuEdit.add_command(label = "Coller", command = None)
            menuBar.add_cascade( label = "Edition", menu = menuEdit)
     
            # Menu exercices
            menu_exercices = Menu(menuBar, tearoff = 0)
            menuBar.add_cascade(label = "Exercices", menu = menu_exercices)
     
            menu_exercices_a = Menu(menu_exercices, tearoff = 0)
            menu_exercices.add_cascade(label='A', menu = menu_exercices_a)
            menu_exercices_a.add_command(label = "A", command = lambda : MyWindow.aff_exercice(self, dic_txt['exA'], dic_img['imgA']))
            menu_exercices_a.add_command(label = "A1", command = lambda : MyWindow.aff_exercice(self, dic_txt['exA1'], dic_img['imgA1']))
            menu_exercices_a.add_command(label = "A2", command = lambda : MyWindow.aff_exercice(self, dic_txt['exA2'], dic_img['imgA2']))
            menu_exercices_a.add_command(label = "A3", command = lambda : MyWindow.aff_exercice(self, dic_txt['exA3'], dic_img['imgA3']))
            #etc.
     
            menu_exercices_b = Menu(menu_exercices, tearoff = 0)
            menu_exercices.add_cascade(label='B', menu = menu_exercices_b)
            menu_exercices_b.add_command(label = "B", command = lambda : MyWindow.aff_exercice(self, dic_txt['exB'], dic_img['imgB']))
            menu_exercices_b.add_command(label = "B1", command = lambda : MyWindow.aff_exercice(self, dic_txt['exB1'], dic_img['imgB1']))
            menu_exercices_b.add_command(label = "B2", command = lambda : MyWindow.aff_exercice(self, dic_txt['exB2'], dic_img['imgB2']))
     
            menu_exercices_c = Menu(menu_exercices, tearoff = 0)
            menu_exercices.add_cascade(label='C', menu = menu_exercices_c)
            menu_exercices_c.add_command(label = "C", command = lambda : MyWindow.aff_exercice(self, dic_txt['exC'], dic_img['imgC']))
            menu_exercices_c.add_command(label = "C1", command = lambda : MyWindow.aff_exercice(self, dic_txt['exC1'], dic_img['imgC1']))
            # etc.
     
     
            menuHelp = Menu(menuBar, tearoff = 0)
            menuHelp.add_command(label = "A propos", command = self.a_propos)
            menuBar.add_cascade( label = "Aide", menu = menuHelp)
     
            self.config(menu = menuBar)
     
     
        def openFile(self):
            file = askopenfilename(title="Choisissez un fichier à ouvrir", 
                    filetypes=[("PNG image", ".png"), ("GIF image", ".gif"), ("All files", ".*")])
            print( file )
     
        #Fonction permettant d'afficher des images dans une fenêtre gauche et des textes dans une fenêtre droite
        def aff_exercice(self, txt, img):
            text1 = Text(window, height = 30, width = 50)
            photo = PhotoImage(file = img) 
            text1.insert(END, '\n')
            text1.image_create(END, image = photo)
            text1.grid(row = 3, column = 1)
     
            text2 = Text(window, height = 30, width = 50)
            scroll = Scrollbar(window, command = text2.yview)
            text2.configure(yscrollcommand = scroll.set)
            text2.configure(wrap = 'word')
            text2.tag_configure('bold_italics', font = ('Arial', 12, 'bold', 'italic'))
            text2.tag_configure('big', font=('Verdana', 20, 'bold'))
            text2.tag_configure('color',
                            foreground = '#476042',
                            font = ('Tempus Sans ITC', 12, 'bold'))
            quote = txt
            text2.insert(END, quote, 'color')
            text2.grid(row = 3, column = 2, padx = 10, pady = 5)
            scroll.grid(side=RIGHT, fill=Y)
     
        def a_propos():
            tkinter.messagebox.showinfo("A propos","Programme Lafay \ P.Y.D \ 2019")
     
     
    window = MyWindow()
    window.mainloop()
    Voilà je fais donc appel aux vrais développeurs pour m'aider, si cela est possible. Merci de m'avoir lu et merci de votre temps.

  2. #2
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 801
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 801
    Billets dans le blog
    1
    Par défaut
    Bonjour

    Citation Envoyé par dustman Voir le message
    je me suis dit, rien de tel qu'un programme perso pour que ça rentre.
    Excellent auto-conseil

    Citation Envoyé par dustman Voir le message
    1 dictionnaire pour les textes, 1 dictionnaire pour les images.
    Tu pourrais aussi n'avoir qu'un seul dictionnaire qui se subdivise en "texte" et "image".
    Exemple
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    exo={
    	"ExeciceA" : {
    		"description" : "Pectauraux+Biceps",
    		"images" : ("imgA1", "imgA2"),
    	},
    	"ExeciceB" : {
    		"description" : "Dorsaux",
    		"images" : ("imgB1", "imgB2"),
    	},
    }
    Plus tu prépares tes éléments de façon identiques, plus tu auras de facilités pour les traiter automatiquement

    Citation Envoyé par dustman Voir le message
    Mon problème principal étant le suivant :

    En bon amateur que je suis, j'ai créé mon menu "Exercices" de sorte à ce que chaque commande pointe vers 1 exercice. Sachant qu'il y en a 65 environs, vous voyez un peu le tableau... Je sais que je peux utiliser une boucle pour simplifier mon code et ne pas avoir à taper une ligne de code par exercice, mais je n'arrive pas, malgré de nombreux tests sur l'interpréteur, à trouver une solution qui fonctionne.
    Tu peux remplacer un code de ce type
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    menu_exercices_a.add_command(label = "A", command = lambda : MyWindow.aff_exercice(self, dic_txt['exA'], dic_img['imgA']))
    menu_exercices_a.add_command(label = "A1", command = lambda : MyWindow.aff_exercice(self, dic_txt['exA1'], dic_img['imgA1']))
    menu_exercices_a.add_command(label = "A2", command = lambda : MyWindow.aff_exercice(self, dic_txt['exA2'], dic_img['imgA2']
    menu_exercices_a.add_command(label = "A3", command = lambda : MyWindow.aff_exercice(self, dic_txt['exA3'], dic_img['imgA3']))

    Par une boucle écrite ainsi
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for x in ("A", "A1", "A2", "A3"):
    	menu_exercices_a.add_command(label = x, command = lambda : MyWindow.aff_exercice(self, dic_txt['ex%s' % x], dic_img['img%s' % x]))

    Après tu remarqueras que tu dois faire de même avec les "B" et les "C"... alors que si tu avais nommé tes exercices de façon plus "synthétique" tu aurais alors pu tout factoriser dans une boucle unique. Mais bon, avec l'entrainement viendra l'expérience
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Membre averti
    Homme Profil pro
    débutant
    Inscrit en
    Septembre 2017
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : débutant
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Septembre 2017
    Messages : 12
    Par défaut
    Tu pourrais aussi n'avoir qu'un seul dictionnaire qui se subdivise en "texte" et "image".
    Exemple

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    exo={
    	"ExeciceA" : {
    		"description" : "Pectauraux+Biceps",
    		"images" : ("imgA1", "imgA2"),
    	},
    	"ExeciceB" : {
    		"description" : "Dorsaux",
    		"images" : ("imgB1", "imgB2"),
    	},
    }
    Plus tu prépares tes structures de façon concise, plus tu auras de facilités pour les traiter.

    Justement j'ai déjà créé un dictionnaire semblable pour cette prochaine étape.


    Tu peux remplacer un code de ce type

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    menu_exercices_a.add_command(label = "A", command = lambda : MyWindow.aff_exercice(self, dic_txt['exA'], dic_img['imgA']))
    menu_exercices_a.add_command(label = "A1", command = lambda : MyWindow.aff_exercice(self, dic_txt['exA1'], dic_img['imgA1']))
    menu_exercices_a.add_command(label = "A2", command = lambda : MyWindow.aff_exercice(self, dic_txt['exA2'], dic_img['imgA2']
    menu_exercices_a.add_command(label = "A3", command = lambda : MyWindow.aff_exercice(self, dic_txt['exA3'], dic_img['imgA3']))

    Par une boucle écrite ainsi

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for x in ("A", "A1", "A2", "A3"):
    	menu_exercices_a.add_command(label = x, command = lambda : MyWindow.aff_exercice(self, dic_txt['ex%s' % x], dic_img['img%s' % x]))
    [/QUOTE]

    Merci beaucoup pour cette boucle, qui fonctionne mais qui ne m'affiche que le dernier élément, à savoir "A3". J'ai raté quelque chose penses-tu ?

  4. #4
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 681
    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 681
    Par défaut
    Salut,

    Citation Envoyé par dustman Voir le message
    Merci beaucoup pour cette boucle, qui fonctionne mais qui ne m'affiche que le dernier élément, à savoir "A3". J'ai raté quelque chose penses-tu ?
    L'utilisation de lambda pour fabriquer des fonctions qui dépendent de l'indice de la boucle est subtil...
    Il faut stocker la variable de boucle dans les arguments par défaut de cette façon:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for x in ("A", "A1", "A2", "A3"):
    	menu_exercices_a.add_command(label = x, command = lambda x=x : MyWindow.aff_exercice(self, dic_txt['ex%s' % x], dic_img['img%s' % x]))
    et éventuellement revoir ce qui se rapporte aux fermetures/closures.

    Mais puisque vous connaissez un peu la POO, questionnez vous sur l'intérêt de créer une classe Exercice puisque c'est un objet que vous allez fabriquer en multiples exemplaires... et qui serait une alternative aux closures.

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

  5. #5
    Membre averti
    Homme Profil pro
    débutant
    Inscrit en
    Septembre 2017
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : débutant
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Septembre 2017
    Messages : 12
    Par défaut
    Wow en effet c'est subtile ! Simple mais subtile.

    Merci beaucoup pour toutes ces réponses et effectivement, je vais (je dois) me pencher sur le concept des fermetures.

    Bonne journée.

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

Discussions similaires

  1. Créer des tables en fonction d'une colonne
    Par marcelstan dans le forum SAS Base
    Réponses: 1
    Dernier message: 27/06/2016, 17h59
  2. [AC-2013] Créer un état en fonction d'une donnée
    Par Liks71 dans le forum Access
    Réponses: 2
    Dernier message: 23/06/2016, 09h48
  3. créer une fonction recevant une liste L et renvoyant la liste M
    Par 1997gaetan dans le forum Général Python
    Réponses: 10
    Dernier message: 25/10/2015, 05h38
  4. Menu en fonction d'une liste
    Par ebaoo dans le forum Langage
    Réponses: 2
    Dernier message: 01/06/2010, 17h25
  5. Afficher un menu en fonction d'une session
    Par sadigoun dans le forum Langage
    Réponses: 6
    Dernier message: 18/01/2008, 00h50

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