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.