Voici le code qui a généré les images de la section précédente. Il est assez abondamment commenté, aussi j'espère que vous n'aurez pas de problème à le suivre. Lancez-le et modifiez-le à souhait.
1 #!/usr/bin/env python
2
3 # exemple boite.py
4
5 import pygtk
6 pygtk.require('2.0')
7 import gtk
8 import sys, string
9
10 # Cette fonction nous aide a creer une nouvelle HBox remplie de boutons+etiquettes.
11 # Des arguments pour les variables qui nous interessent lui sont transmis. On n'affiche
12 # pas la boite (avec show()), mais on affiche tout ce qui se trouve a l'interieur.
13
14 def creer_boite(homogeneous, spacing, expand, fill, padding):
15
16 # On cree une nouvelle boite avec les valeurs
17 # transmises pour "homogeneous" et "spacing"
18 boite = gtk.HBox(homogeneous, spacing)
19
20 # On cree une serie de boutons, toujours avec les valeurs transmises.
21 bouton = gtk.Button("boite.pack")
22 boite.pack_start(bouton, expand, fill, padding)
23 bouton.show()
24
25 bouton = gtk.Button("(bouton,")
26 boite.pack_start(bouton, expand, fill, padding)
27 bouton.show()
28
29 # On cree un bouton dont l'etiquette dependra de la valeur
30 # de "expand".
31 if expand == True:
32 bouton = gtk.Button("True,")
33 else:
34 bouton = gtk.Button("False,")
35
36 boite.pack_start(bouton, expand, fill, padding)
37 bouton.show()
38
39 # Meme principe que ci-dessus, mais cette fois avec la
40 # formulation abregee
41 bouton = gtk.Button(("False,", "True,")[fill==True])
42 boite.pack_start(bouton, expand, fill, padding)
43 bouton.show()
44
45 chaine_pad = "%d)" % padding
46
47 bouton = gtk.Button(chaine_pad)
48 boite.pack_start(bouton, expand, fill, padding)
49 bouton.show()
50 return boite
51
52 class BoitesPLacement:
53 def evnmt_delete(self, widget, evenement, donnees=None):
54 gtk.main_quit()
55 return False
56
57 def __init__(self, numero):
58
59 # Creation de notre fenetre
60 self.fenetre = gtk.Window(gtk.WINDOW_TOPLEVEL)
61
62 # N'oubliez pas de connecter le signal "delete_event"
63 # a la fenetre principale. Cela donne au programme
64 # un comportement plus intuitif.
65 self.fenetre.connect("delete_event", self.evnmt_delete)
66 self.fenetre.set_border_width(10)
67
68 # On cree une boite verticale (VBox) pour y placer nos boites
69 # horizontales. Ainsi on peut empiler les boites horizontales
70 # remplies de boutons les unes sur les autre dans la VBox.
71 boite1 = gtk.VBox(False, 0)
72
73 # Sur quel scenario partons-nous ? (cf. images de la section 4.2)
74 if numero == 1:
75 # Creation d'une nouvelle etiquette.
76 etiquette = gtk.Label("HBox(False, 0)")
77
78 # On aligne l'etiquette a gauche. Nous verrons cette methode
79 # ainsi que d'autres dans la section sur les attributs des widgets.
80 etiquette.set_alignment(0, 0)
81
82 # On place l'etiquette dans la boite verticale (la VBox boite1).
83 # Souvenez-vous que les widgets ajoutes a une VBox seront places
84 # les uns sur les autres, dans l'ordre.
85 boite1.pack_start(etiquette, False, False, 0)
86
87 # On affiche l'etiquette.
88 etiquette.show()
89
90 # On appelle notre fonction creer_boite en lui transmettant :
91 # homogeneous=False, spacing=0, expand=False, fill=False, padding=0
92 boite2 = creer_boite(False, 0, False, False, 0)
93 boite1.pack_start(boite2, False, False, 0)
94 boite2.show()
95
96 # On appelle notre fonction creer_boite en lui transmettant :
97 # homogeneous=False, spacing=0, expand=True, fill=False, padding=0
98 boite2 = creer_boite(False, 0, True, False, 0)
99 boite1.pack_start(boite2, False, False, 0)
100 boite2.show()
101
102 # homogeneous=False, spacing=0, expand=True, fill=True, padding=0
103 boite2 = creer_boite(False, 0, True, True, 0)
104 boite1.pack_start(boite2, False, False, 0)
105 boite2.show()
106
107 # Creation d'un separateur. On en apprendra plus sur ce widget
108 # ulterieurement mais il est assez simple.
109 separateur = gtk.HSeparator()
110
111 # On place le separateur dans la VBox. Gardez bien a l'esprit que
112 # tout ces widgets sont places dans une VBox, ils sont donc
113 # empiles les uns sur les autres.
114 boite1.pack_start(separateur, False, True, 5)
115 separateur.show()
116
117 # On cree une autre etiquette, et on l'affiche.
118 etiquette = gtk.Label("HBox(True, 0)")
119 etiquette.set_alignment(0, 0)
120 boite1.pack_start(etiquette, False, False, 0)
121 etiquette.show()
122
123 # homogeneous=True, spacing=0, expand=True, fill=False, padding=0
124 boite2 = creer_boite(True, 0, True, False, 0)
125 boite1.pack_start(boite2, False, False, 0)
126 boite2.show()
127
128 # homogeneous=True, spacing=0, expand=True, fill=True, padding=0
129 boite2 = creer_boite(True, 0, True, True, 0)
130 boite1.pack_start(boite2, False, False, 0)
131 boite2.show()
132
133 # Un autre separateur.
134 separateur = gtk.HSeparator()
135 # Les trois derniers arguments de pack_start() sont :
136 # expand, fill, padding.
137 boite1.pack_start(separateur, False, True, 5)
138 separateur.show()
139 elif numero == 2:
140 # On cree une etiquette, souvenez-vous que boite1 est une VBox,
141 # creee vers le debut de __init__()
142 etiquette = gtk.Label("HBox(False, 10)")
143 etiquette.set_alignment( 0, 0)
144 boite1.pack_start(etiquette, False, False, 0)
145 etiquette.show()
146
147 # homogeneous=False, spacing=10, expand=True, fill=False, padding=0
148 boite2 = creer_boite(False, 10, True, False, 0)
149 boite1.pack_start(boite2, False, False, 0)
150 boite2.show()
151
152 # homogeneous=False, spacing=10, expand=True, fill=True, padding=0
153 boite2 = creer_boite(False, 10, True, True, 0)
154 boite1.pack_start(boite2, False, False, 0)
155 boite2.show()
156
157 separateur = gtk.HSeparator()
158 # Les trois derniers arguments de pack_start() sont :
159 # expand, fill, padding.
160 boite1.pack_start(separateur, False, True, 5)
161 separateur.show()
162
163 etiquette = gtk.Label("HBox(False, 0)")
164 etiquette.set_alignment(0, 0)
165 boite1.pack_start(etiquette, False, False, 0)
166 etiquette.show()
167
168 # homogeneous=False, spacing=0, expand=True, fill=False, padding=10
169 boite2 = creer_boite(False, 0, True, False, 10)
170 boite1.pack_start(boite2, False, False, 0)
171 boite2.show()
172
173 # homogeneous=False, spacing=0, expand=True, fill=True, padding=10
174 boite2 = creer_boite(False, 0, True, True, 10)
175 boite1.pack_start(boite2, False, False, 0)
176 boite2.show()
177
178 separateur = gtk.HSeparator()
179 # Les trois derniers arguments de pack_start() sont :
180 # expand, fill, padding.
181 boite1.pack_start(separateur, False, True, 5)
182 separateur.show()
183
184 elif numero == 3:
185
186 # Ce scenario est la pour montrer qu'avec pack_end() on peut aligner
187 # les widgets a droite. D'abord, creons une boite, comme avant.
188 boite2 = creer_boite(False, 0, False, False, 0)
189
190 # on cree l'etiquette que l'on alignera a droite.
191 etiquette = gtk.Label("fin")
192 # On la place avec pack_end(), elle va se placer a l'extremite
193 # droite de la HBox creee par l'appel a creer_boite().
194 boite2.pack_end(etiquette, False, False, 0)
195 # On affiche l'etiquette.
196 etiquette.show()
197
198 # On place boite2 dans boite1
199 boite1.pack_start(boite2, False, False, 0)
200 boite2.show()
201
202 # Un separateur pour le bas.
203 separateur = gtk.HSeparator()
204
205 # Cette methode fixe les dimensions du separateur (400 pixels de large
206 # pour 5 pixels de haut). C'est pour que la HBox qu'on vient de creer
207 # fasse aussi 400 de large, et que l'etiquette "fin" soit bien separee
208 # des autres widgets de la HBox. Autrement, tous les widgets de la
209 # HBox seraient places aussi pres l'un de l'autre que possible.
210 separateur.set_size_request(400, 5)
211 # On place le separateur dans la HBox (boite1) creee vers le debut
212 # de __init__()
213 boite1.pack_start(separateur, False, True, 5)
214 separateur.show()
215
216 # On cree une autre HBox. On peut en utiliser autant qu'on veut !
217 boitequitter = gtk.HBox(False, 0)
218
219 # Notre bouton "Quitter".
220 bouton = gtk.Button("Quitter")
221
222 # Lorsqu'on clique sur le bouton, le signal emis doit terminer le programme.
223 bouton.connect_object("clicked", gtk.main_quit, self.fenetre)
224 # On place le bouton dans la HBox boitequitter.
225 # Les trois derniers arguments de pack_start() sont :
226 # expand, fill, padding.
227 boitequitter.pack_start(bouton, True, False, 0)
228 # On place boitequitter dans la VBox (boite1)
229 boite1.pack_start(boitequitter, False, False, 0)
230
231 # On place la VBox boite1 (qui contient maintenant tous nos widgets)
232 # dans la fenetre principale.
233 self.fenetre.add(boite1)
234
235 # Et on affiche ce qui reste a afficher.
236 bouton.show()
237 boitequitter.show()
238
239 boite1.show()
240 # La fenetre en dernier, afin que tout s'affiche d'un coup.
241 self.fenetre.show()
242
243 def main():
244 # Et bien sur, notre boucle principale.
245 gtk.main()
246 # Le controle revient ici lorsque main_quit() est appelee.
247 return 0
248
249 if __name__ =="__main__":
250 if len(sys.argv) != 2:
251 sys.stderr.write("La commande doit etre de la forme \"boite.py num\", avec num = 1 ou 2 ou 3\n")
252 sys.exit(1)
253 BoitesPLacement(string.atoi(sys.argv[1]))
254 main()
En route pour une brève visite guidée du code :
De la ligne 14 à la ligne 50, on définit une fonction creer_boite() qui nous facilitera la creation des boites horizontales. À chaque appel, elle créera une HBox et la remplira de cinq boutons en respectant les paramètres spécifiés. Sa valeur de retour est une référence à elle-même.
Puis on définit le constructeur __init__() de la classe BoitesPLacement (lignes 52 à 241), qui crée une fenêtre et une boite verticale enfant. Cette dernière contiendra d'autre widgets dont la nature et la disposition dépendent de l'argument qu'elle reçoit. Si elle recoit 1, elle crée une fenêtre montrant les cinq arrangements de widgets que l'on peut obtenir en jouant sur les paramètres homogeneous , expand et fill (lignes 75 à 138). Si elle recoit 2, elle crée une fenêtre qui affiche cette fois-ci les différentes combinaisons de remplissage offertes par les paramètres spacing et padding (lignes 140 à 182). Enfin, en recevant 3, la fenêtre créée par la fonction montrera l'utilisation des méthodes pack_start() et pack_end(), la première pour aligner les boutons à gauche et la seconde pour aligner une étiquette à droite (lignes 188 à 214). Aux lignes 215 à 235, on crée une boite horizontale contenant un bouton, et on la place dans la boite verticale. Le signal "clicked" du bouton est connecté à la fonction PyGTK main_quit() pour terminer le programme.
Aux lignes 250 à 252, on vérifie la ligne de commande : celle-ci doit comporter un seul argument. Dans le cas contraire, on sort du programme avec la fonction sys.exit(). La ligne 253 crée une instance de BoitesPLacement et la ligne 254 invoque la fonction main() qui va initialiser la boucle du réceptionnaire d'évènements de GTK.
Dans ce programme exemple, aucune référence de widget n'est enregistrée dans un attribut d'instance (sauf pour la fenêtre). En effet, nos widgets ne seront plus sollicités après leur création.