Bonjour,

J'ai d'un côté un programme qui fonctionne (pendu), et de l'autre une GUI qui fonctionne également (code ci-dessous, avec un dessin qui ultérieurement sera un pendu).
Question classique (de ce que j'en ai vu) : comment relier les deux ?


J'ai lu qu'il y avait l'option MVC, mais c'est un peu une recette toute faite, et ce n'est pas très pédagogique (pour moi en tout cas). J'ai trouvé sur le forum :
https://www.developpez.net/forums/d9...es-distinctes/

Ou ces post, mais qui fonctionnent (si j'ai compris) comme de la programmation fonctionnelle :
https://www.developpez.net/forums/d2...u-tkinter-isn/
https://www.developpez.net/forums/d2...fichage-entry/

L'exemple du tuto est également dans une logique de programmation fonctionnelle :
https://python.developpez.com/cours/.../?page=page_10


Avant de regarder ce côté "organisation à trois" de la VMC, j'aimerai pouvoir faire communiquer la GUI et le Core de manière bidirectionnelle (et ensuite étendre le fonctionnement à un modèle type MVC). Je pense que c'est une base de révision/progrès sur la POO.

Il me semble avoir compris que les classes doivent communiquer entre elles. Et j'ai l'impression d'avoir raté quelque chose : les instances recoivent et donnent des données, mais je ne comprend pas comment (comment créer les liens entre les instances ?).

Dans le sens GUI->Core je récupère les attributs de l'instance de la classe Core. Mais celà ne me parait pas bien "propre" ?
Dans l'autre sens, je sèche... à part réaliser une programmation fonctionnelle qui ne dit pas son nom (mais je souhaite rester dans une logique POO).

J'ai un bouton command dans la GUI qui appelle une fonction :
- dois-je prendre à chaque fois la méthode de la classe Core ?
- dois-je instancier un objet de la classe Core (ou rendre "Core" en temps que classe mère, l'héritage devant suffire) ?
- bref, comment créer une fonction "command=input" qui renvoie la valeur dans la bonne case (voir code ci-dessus) ?

J'aimerai éviter de bricoler en gérant la classe Core comme un module. Comment le faire en POO proprement (ou à la mode Python) ?
Si je dois être synthétique après ce long message : quelle architecture et quels liens ?

Merci pour votre aide.

Code python : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
 
#!/usr/bin/python3.5
# -*-coding:utf-8 -*
 
import tkinter
from turtle import *
from couleurs import COLORS
from random import choice
import pickle
 
 
class Jeu():
    def __init__(self, Scores_recuperes = {}, Scores_charges = 0):
        self.Scores_recuperes = Scores_recuperes
        self.Scores_charges = Scores_charges
        self.nom = ''
        self.score_joueur = 0
        self.message = 'En attente'
        self.mot=''
        self.mot_partiel = list(8 * '*')
        self.compteur = 0
        self.lettre = ''
        self.tentativesmax = 0
        self.entree = ''
 
    def identifiant(self):
        if self.nom in self.Scores_recuperes.keys():
            self.score_joueur = self.Scores_recuperes[self.nom]
 
            self.message = 'Votre précédent score était de :' + str(score_joueur)
 
        else:
            self.Scores_recuperes[self.nom] = self.score_joueur
            self.message = 'Vous êtes enregistré' + str(self.nom)
            with open('score', 'wb') as Scores:             # Enregistrement de l'identifiant dans le dictionnaire et dans scores
                self.Scores_charges = pickle.dump(self.Scores_recuperes, Scores)
        return self.Scores_recuperes, self.score_joueur
 
    def chercher_lettre_dans_mot(self):
        nb_occurences = self.mot.count(self.lettre)
        if nb_occurences == 0 :
            self.message = str(self.lettre) + ' pas dans le mot cherché.'
            return False
        return True
 
    def afficher_mot_partiel(self):
        for i,x in enumerate(self.mot):
            if x == self.lettre : self.mot_partiel[i] = self.lettre
        return self.mot_partiel
 
 
    def chargement_donnees(self):
        with open("donnees.py", "r") as fichier:
            donnees = fichier.read()
        self.mot = choice(donnees.split()[:-1]).lower()
        self.tentativesmax = int(donnees.split()[-1])
        self.compteur = self.tentativesmax + self.score_joueur
        return
 
    def core(self):
 
        while self.compteur >= 0 and self.mot != ''.join(self.mot_partiel):
            self.lettre = '' # Il faut rentrer qqch ici depuis la GUI : str(input("Choix d'une lettre : "))
            self.message = "Il reste {} tentatives.".format(self.compteur)
 
            if self.chercher_lettre_dans_mot() == False:
                self.compteur -= 1
                continue
 
            else:
                self.mot_partiel = self.afficher_mot_partiel()
                self.message = str(''.join(self.mot_partiel))
 
        if self.mot == ''.join(self.mot_partiel):
            self.message = "Mot trouvé : {} ! Score = {}".format(''.join(mot_partiel), compteur)
            self.Scores_recuperes[self.nom] = compteur
 
        else:
            self.message = "Perdu. Le mot était : " + str(self.mot)
            self.Scores_recuperes[self.nom] = self.compteur+1
 
        with open('score', 'wb') as Scores:
            self.Scores_charges = pickle.dump(self.Scores_recuperes, Scores)
 
 
    def jeux(self, nom):
        # Identification et initialisation du score
        self.nom = nom # il faut rentrer qqch ici depuis la GUI : input("Quel votre nom ? ")
        self.Scores_recuperes, self.score_joueur = self.identifiant()
 
        # Chargement des donnees
        self.chargement_donnees()
 
        # Début du jeu
        self.core()
 
 
class InterfaceGraphique(tkinter.Tk, Jeu):
    def __init__(self,parent):
        tkinter.Tk.__init__(self)
        Jeu.__init__(self)
        self.a = Jeu() #Instanciation avant l'ouverture de la fenêtre?
        self.fenetre()
 
 
    def fenetre(self, largeur=200, hauteur=200) :
        '''Une zone graphique et plusieurs boutons'''
        self.largeur = largeur
        self.hauteur = hauteur
 
        #Deux frames : frame1 à gauche pour le dessin, et frame2 à droite pour les autres widgets
        #Les frames sont positionnées avec grid
 
 
        #Frame contenant la zone de dessin et initialisation d'un canvas
        #Positionnement de la zone de dessin avec la méthode grid et une seule case (extension pour plus tard)
 
        self.frame1 = tkinter.Frame()
        self.frame1.grid(column=0,row=0)
 
        self.zone_dessin = tkinter.Canvas(self.frame1, width=self.largeur, height=self.hauteur)
        self.zone_dessin.grid(column=0,row=0)
 
 
        #Frame contenant les boutons et labels
        #Positionnement des widgets avec une deuxième méthode grid dans frame2
 
        #frame
        self.frame2 = tkinter.Frame()
        self.frame2.grid(column=1,row=0)
 
        #Boutons
        b_start = tkinter.Button(self.frame2, command = self.RAZ, text = "Rejouer une partie", fg="green")
        b_start.grid(column=0,row=0)
        b_quit = tkinter.Button(self.frame2, command = self.destroy, text = "Quitter", fg="red")
        b_quit.grid(column=0,row=7)       
 
        #Champ texte
            #Variable de contrôle
        self.value = tkinter.StringVar(self)
        self.value.set("Quel est votre nom ?")
            #Champ
        self.entree = tkinter.Entry(self.frame2, textvariable=self.value, width=30)
        self.entree.grid(column=0,row=4)
            #Enregistrement de la saisie
        self.entree.bind("<Return>", self.affichersaisie) 
            #Description du champ
        lab1 = tkinter.Label(self.frame2, text='Résultat de la saisie')
        lab1.grid(column=0,row=5)
             #Affichage de la saisie
        self.lab2 = tkinter.Label(self.frame2, text=self.value.get())
        self.lab2.grid(column=0,row=6)
 
 
    def affichersaisie(self,event):
        '''Affiche la saisie du widget "entree" dans le label "lab2"'''
        self.lab2["text"] = self.entree.get() # les widgets se comportent comme des dictionnaires ou, sinon, utiliser self.lab2.configure(text = self.entree.get())
        #self.a.jeux('Damien')
        return
 
 
    def RAZ(self):
        ''' Remise à zéro pour une nouvelle partie'''
        pass
 
    def dessiner(self):
        '''Fonction dessiner avec Turtle'''
 
        #Nettoyage de la zone de dessin : supression du canvas et création d'un nouveau
 
        self.zone_dessin.grid_forget()
        self.zone_dessin = tkinter.Canvas(self.frame1, width=self.largeur, height=self.hauteur)
        self.zone_dessin.grid(column=0,row=0)
 
        #Module Turtle
 
        t=RawPen(self.zone_dessin)
 
        #Début du dessin Turtle
 
        x = 0
        L = self.largeur
        H = self.hauteur
        t.up()
        t.goto(-L, H)
        t.pensize(4)
        while x < 2*self.hauteur :
            t.down()
            t.goto(-L, H)
            t.up()
            x += 15
            L = -L
            if L >0 : H = -self.hauteur+x
            else :
                H = self.hauteur-x
            t.pencolor(choice(COLORS))
 
 
 
 
if __name__ == "__main__":
    # Création du fichier scores ou chargement si existant
    try:
        with open("score", "rb") as Scores:
            Scores_recuperes = pickle.load(Scores)
    except :
        Scores_recuperes = {}
        with open('score', 'wb') as Scores:
            Scores_charges = pickle.dump(Scores_recuperes, Scores)
 
    #Lancement du jeu ici ?
    '''a = Jeu()
    a.jeux()'''
 
    #Ouverture fenêtre
    app = InterfaceGraphique(None)
    app.title('Appli Pendu')
 
    app.mainloop()