Vous êtes à peu près ici : Accueil  »   tutoriel PyGTK  »   PyGTK : sommaire

4.3. Démonstration de placement avec les boites

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.