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
| from tkinter import *
app = Tk()
app.geometry('160x130+10+10')
frame = Frame(app, name = 'frame', bg='pink')
bouton1 = Button(frame, name='bouton1', bg='yellow')
bouton2 = Button(app, name='bouton2', text='Bouton2')
message = Label(frame, text='maître/esclave \nou parent/enfant ?')
frame.pack(padx=20)
bouton1.pack()
bouton2.pack(in_=bouton1, padx=10, pady=10)
message.pack(padx=10, pady=10)
print('app =', app)
print('app.children =', app.children)
print('bouton2.master =', bouton2.master)
print('\nbouton1 =', bouton1)
print('bouton1.master =', bouton1.master)
print('bouton2 =', bouton2)
print('\nid(message) =', id(message))
print('messsage =', message)
"""
La notion parent/enfant (parent/child) de tkinter n'a rien avoir avec celle
concernant l'héritage dans le langage python.
Les termes parent/enfant et maître/esclave (master/slave) de tkinter sont
généralement utilisés de manière synonyme dans la littérature que l'on trouve
sur internet. Pourtant, dans la documentation tkinter, il semble qu'il y ait
une distinction assez claire :
- parent/enfant signifie 'widget conteneur'/'widget contenu' au sens visuel.
- maître/esclave a le même sens mais concerne le geometry manager.
Le 'widget contenu' est le même dans les deux cas. L'esclave est donc toujours
l'enfant. Par contre, le maître est parfois un conteneur lui-même contenu dans
le parent.
Dans l'instruction < bouton2 = Button(app, ...) >, l'argument 'app' désigne le
widget 'parent' dans lequel sera contenu, au sens visuel du terme, le widget
'enfant' bouton2. On peut vérifier cela en tapant dans la console :
- print(app) : renvoie -> '.' qui désigne la racine
- print(app.children) : renvoie -> frame ainsi que bouton2
- print(bouton2.master) : renvoie -> app
Le nom 'master' est un choix maladroit pour désigner l'attribut. Il aurait été
plus judicieux de l'appeler 'bouton2.parent'. Cette maladresse est probablement
la cause du mélange des termes que l'on constate dans la littérature internet.
Par défaut, le geometry manager utilise le parent indiqué dans l'instruction
< bouton2 = Button(app, ...) > comme étant le widget 'master' pour le packing,
c'est à dire app dans cet exemple. Mais ici ce n'est pas le cas à cause de
l'instruction bouton2.pack(in_=bouton1, ...) qui désigne bouton1 comme le
master. On peut vérifier cela en tapant dans la console :
- bouton2.pack_info() : renvoie -> bouton1 (comme master)
- bouton1.pack_slaves() : renvoie -> bouton2 (comme esclave)
Le master désigné par l'option 'in_' ne peut être que le parent (valeur par
défaut) ou un enfant du parent. La conséquence de cette restriction est que le
parent reste toujours le conteneur global, et que les méthodes parent.destroy() et
master.destroy() provoquent toutes deux la destruction du widget ainsi packé.
REMARQUE :
La relation parent/enfant est utilisée par tkinter pour construire les noms des
widgets et organiser leur hiérarchie graphique par des 'paths', un peu à la
manière des répertoires/sous-répertoires. On peut voir cela en tapant dans la
console :
- print(bouton1) : renvoie -> '.frame.bouton1'
- print(bouton1.master) : renvoie -> '.frame'
- print(bouton2) : renvoie -> '.bouton2'
Si aucun nom n'est donné au widget au moment de son instanciation par l'option
'name', tkinter fabrique le nom à l'aide de l' id. On peut voir cela en tapant
dans la console :
- id(message) : renvoie -> xxxxxxxx
- str(message) : renvoie -> '.frame.xxxxxxxx'
""" |