Les gtk.Image sont des structures de données qui contiennent des images. Ces images peuvent être utilisées à plusieurs endroits.
On peut créer des gtk.Image à partir de pixbufs, de pixmaps, de fichiers contenant des informations soit de type image (XPM, PNG, JPEG, TIFF, etc.) soit de type animation.
On crée un gtk.Image avec la fonction :
image = gtk.Image()
Puis on y charge l'image en utilisant l'une des méthodes suivantes :
image.set_from_pixbuf(pixbuf) image.set_from_pixmap(pixmap, mask) image.set_from_image(image) image.set_from_file(filename) image.set_from_stock(stock_id, size) image.set_from_icon_set(icon_set, size) image.set_from_animation(animation)
pixbuf est un GdkPixbuf, pixmap et mask sont des GdkPixmaps, image est un GdkImage, stock_id est le nom d'un GtkStockItem, icon_set est un GtkIconSet, et animation est une GdkPixbufAnimation. Quant à l'argument size (taille), il peut prendre l'une des valeurs suivantes :
ICON_SIZE_MENU # taille de l'icône : menu ICON_SIZE_SMALL_TOOLBAR # " : petite barre d'outils ICON_SIZE_LARGE_TOOLBAR # " : grande barre d'outils ICON_SIZE_BUTTON # " : bouton ICON_SIZE_DND # " : glisser-déposer ICON_SIZE_DIALOG # " : boite de dialogue
Le moyen le plus simple de créer une image est d'utiliser la méthode set_from_file(), laquelle détermine automatiquement le type de l'image et le charge.
Le programme images.py illustre le chargement de plusieurs types d'images ( goal.gif, pomme-rouge.png, chaos.jpg, important.tif, ballonfoot.gif) dans des gtk.Image, que l'on place ensuite dans des boutons :
Voici le code source :
1 #!/usr/bin/env python
2
3 # exemple images.py
4
5 import pygtk
6 pygtk.require('2.0')
7 import gtk
8
9 class ImagesExemple:
10 # Si elle est invoquee (via le "delete_event"), cette fonction ferme l'application
11 def fermer_application(self, widget, evnmt, data=None):
12 gtk.main_quit()
13 return False
14
15 # Cette fonction est invoquee quand on clique sur le bouton. Elle affiche un message.
16 def clic_bouton(self, widget, data=None):
17 print "Clic sur le bouton %s" % data
18
19 def __init__(self):
20 # creation de la fenetre principale, et connexion du signal
21 # delete_event a la fermeture de l'application
22 fenetre = gtk.Window(gtk.WINDOW_TOPLEVEL)
23 fenetre.connect("delete_event", self.fermer_application)
24 fenetre.set_border_width(10)
25 fenetre.show()
26
27 # Une boite horizontale pour contenir les boutons
28 boite_h = gtk.HBox()
29 boite_h.show()
30 fenetre.add(boite_h)
31
32 animpixbuf = gtk.gdk.PixbufAnimation("goal.gif")
33 image = gtk.Image()
34 image.set_from_animation(animpixbuf)
35 image.show()
36 # un bouton pour contenir le widget image
37 bouton = gtk.Button()
38 bouton.add(image)
39 bouton.show()
40 boite_h.pack_start(bouton)
41 bouton.connect("clicked", self.clic_bouton, "1")
42
43 # creation de plusieurs gtk.Image a partir de donnees de
44 # fichiers, et chargement dans des boutons
45 image = gtk.Image()
46 image.set_from_file("pomme-rouge.png")
47 image.show()
48 # un bouton pour contenir le widget image
49 bouton = gtk.Button()
50 bouton.add(image)
51 bouton.show()
52 boite_h.pack_start(bouton)
53 bouton.connect("clicked", self.clic_bouton, "2")
54
55 image = gtk.Image()
56 image.set_from_file("chaos.jpg")
57 image.show()
58 # un bouton pour contenir le widget image
59 bouton = gtk.Button()
60 bouton.add(image)
61 bouton.show()
62 boite_h.pack_start(bouton)
63 bouton.connect("clicked", self.clic_bouton, "3")
64
65 image = gtk.Image()
66 image.set_from_file("important.tif")
67 image.show()
68 # un bouton pour contenir le widget image
69 bouton = gtk.Button()
70 bouton.add(image)
71 bouton.show()
72 boite_h.pack_start(bouton)
73 bouton.connect("clicked", self.clic_bouton, "4")
74
75 image = gtk.Image()
76 image.set_from_file("ballonfoot.gif")
77 image.show()
78 # un bouton pour contenir le widget image
79 bouton = gtk.Button()
80 bouton.add(image)
81 bouton.show()
82 boite_h.pack_start(bouton)
83 bouton.connect("clicked", self.clic_bouton, "5")
84
85
86 def main():
87 gtk.main()
88 return 0
89
90 if __name__ == "__main__":
91 ImagesExemple()
92 main()
Les pixmaps sont des structures de données qui contiennent des images. Ces images peuvent être utilisées à plusieurs endroits, mais le sont le plus souvent sous la forme d'icônes pour le bureau X ou bien de pointeurs.
Un pixmap de seulement 2 couleurs est un bitmap. Des routines additionnelles existent pour manipuler ce cas à part relativement commun.
Pour comprendre les pixmaps, il vous faut comprendre le fonctionnement du système X Window. Sous X, il n'est pas nécessaire que les applications tournent sur l'ordinateur qui dialogue avec l'utilisateur. Les différentes applications, appelées "clients", communiquent toutes avec un programme qui se charge de l'affichage de la partie graphique ainsi que de la gestion du clavier et de la souris. Ce programme, qui dialogue directement avec l'utilisateur, est appelé un "serveur d'affichage" ou "serveur X". Du fait que la communication peut avoir lieu dans le cadre d'un réseau, il est important que certaines informations soient conservées par le serveur X. Les pixmaps, par exemple, sont stockés dans sa mémoire. Cela signifie que, une fois que des valeurs de pixmaps sont définies, elles n'ont plus besoin d'être à nouveau transmises dans le réseau ; une simple commande sera envoyée pour "afficher le pixmap numéro XYZ à tel endroit". Même si vous n'utilisez pas X avec GTK en ce moment, l'utilisation de structures comme les pixmaps fera tourner convenablement vos programmes sous X.
Pour utiliser des pixmaps dans PyGTK, il nous faut d'abord construire un GdkPixmap en nous servant des fonctions gtk.gdk de PyGTK. Les pixmaps peuvent être créés soit à partir de données en mémoire, soit à partir de données lues dans un fichier. Nous allons examiner les différents appels de création.
pixmap = gtk.gdk.pixmap_create_from_data(window, data, width, height, fg, bg)
On utilise la routine ci-dessus pour crééer un pixmap à partir de données (data) en mémoire. Sa profondeur de couleur est donnée par depth. Si depth vaut -1, la profondeur de couleur sera dérivée de celle de window (fenêtre). Pour représenter les couleurs, chaque pixel utilisera autant de bits de données que mentionné à l'argument depth (profondeur). width (largeur) et height (hauteur) sont spécifiés en pixels. L'argument window doit faire référence à une GdkWindow réalisée, les ressources d'un pixmap n'ayant de sens que dans le contexte de l'écran où il doit être affiché. fg et bg sont les couleurs de premier plan (foreground) et d'arrière plan (background) du pixmap.
Les pixmaps peuvent être créés à partir de fichiers XPM grâce à la fonction :
pixmap, masque = gtk.gdk.pixmap_create_from_xpm(window, transparent_color, filename)
Le format XPM est un représentation lisible d'un pixmap, destinée au système X Window. Il s'agit d'un format trés répandu et de nombreux utilitaires existent pour créer des fichiers images dans ce format. Dans la fonction pixmap_create_from_xpm(), le premier argument est un type GdkWindow — la majorité des widgets GTK possèdent une fenêtre GdkWindow sous-jacente, récupérable par l'attribut window du widget. Le fichier est spécifié à l'argument filename (nom du fichier). Il doit contenir une image au format XPM à charger dans la structure pixmap. Le masque est un bitmap qui indique les bits de pixmap devant être opaques ; il est créé par la fonction. Tous les autres pixels sont colorés en utilisant la couleur scpécifiée par transparent_color (couleur transparente). Vous trouverez ci-dessous un exemple d'utilisation de cette fonction.
Les pixmaps peuvent également être créés à partir de données en mémoire, et ce avec la fonction suivante :
pixmap, masque = gtk.gdk.pixmap_create_from_xpm_d(window, transparent_color, data)
Cette fonction permet d'incorporer de petites images à un programme sous la forme de données au format XPM. Un pixmap sera créé à partir de ces données-là plutôt qu'en lisant celles d'un fichier. Voici un exemple de ces données :
donnees_xpm = [ "16 16 3 1", " c None", ". c #000000000000", "X c #FFFFFFFFFFFF", " ", " ...... ", " .XXX.X. ", " .XXX.XX. ", " .XXX.XXX. ", " .XXX..... ", " .XXXXXXX. ", " .XXXXXXX. ", " .XXXXXXX. ", " .XXXXXXX. ", " .XXXXXXX. ", " .XXXXXXX. ", " .XXXXXXX. ", " ......... ", " ", " " ]
Enfin, la dernière possibilité permet de créer un pixmap vierge, prêt pour les opérations de dessin :
pixmap = gtk.gdk.Pixmap(window, width, height, depth=-1)
window est soit une GdkWindow soit None. Dans le premier cas, depth (profondeur) peut valoir -1 afin d'indiquer que la profondeur doit être déterminée par la fenêtre. Dans le second cas, depth devra être spécifié.
Le programme pixmap.py est un exemple d'utilisation d'un pixmap dans un bouton. La Figure 9.6 en montre le résultat :
Voici le code source :
1 #!/usr/bin/env python
2
3 # exemple pixmap.py
4
5 import pygtk
6 pygtk.require('2.0')
7 import gtk
8
9 # Donnees XPM d'une icone "Ouvrir Fichier"
10 donnees_xpm = [
11 "16 16 3 1",
12 " c None",
13 ". c #000000000000",
14 "X c #FFFFFFFFFFFF",
15 " ",
16 " ...... ",
17 " .XXX.X. ",
18 " .XXX.XX. ",
19 " .XXX.XXX. ",
20 " .XXX..... ",
21 " .XXXXXXX. ",
22 " .XXXXXXX. ",
23 " .XXXXXXX. ",
24 " .XXXXXXX. ",
25 " .XXXXXXX. ",
26 " .XXXXXXX. ",
27 " .XXXXXXX. ",
28 " ......... ",
29 " ",
30 " "
31 ]
32
33 class ExemplePixmap:
34 # Si elle est invoquee (via le "delete_event"), cette fonction ferme l'application
35 def fermer_application(self, widget, evnmt, data=None):
36 gtk.main_quit()
37 return False
38
39 # Fonction invoquee par un clic sur le bouton. Elle affiche juste un message.
40 def clic_bouton(self, widget, data=None):
41 print "Clic sur le bouton"
42
43 def __init__(self):
44 # creation de la fenetre principale, et connexion du signal
45 # delete_event a la fermeture de l'application
46 fenetre = gtk.Window(gtk.WINDOW_TOPLEVEL)
47 fenetre.connect("delete_event", self.fermer_application)
48 fenetre.set_border_width(10)
49 fenetre.show()
50
51 # venons-en a la creation du pixmap a partir des donnees XPM
52 pixmap, masque = gtk.gdk.pixmap_create_from_xpm_d(fenetre.window,
53 None,
54 donnees_xpm)
55
56 # Creation d'un widget gtk.Image pour contenir le pixmap
57 image = gtk.Image()
58 image.set_from_pixmap(pixmap, masque)
59 image.show()
60
61 # Creation d'un bouton pour contenir le gtk.Image
62 bouton = gtk.Button()
63 bouton.add(image)
64 fenetre.add(bouton)
65 bouton.show()
66
67 bouton.connect("clicked", self.clic_bouton)
68
69 def main():
70 gtk.main()
71 return 0
72
73 if __name__ == "__main__":
74 ExemplePixmap()
75 main()
Les pixmap ont malgré tout cet inconvénient que l'objet affiché est toujours rectangulaire, quelle que soit l'image. On aimerait bien pouvoir créer des bureaux ou des applications avec des icônes aux formes plus naturelles. Des boutons ronds seraient par exemple bienvenus dans l'interface d'un jeu. C'est ici qu'entrent en jeu les fenêtres adaptées.
Il s'agit en fait simplement d'un pixmap dont les pixels d'arrière-plan sont transparents. Ainsi, lorsque l'image d'arrière-plan est multicolore, on ne l'encombre pas avec la bordure rectangulaire inadaptée de notre icône. Le programme d'exemple brouette.py affiche une image représentant une brouette pleine sur le bureau. La Figure 9.7 montre cette brouette par dessus une fenêtre de terminal :
Voici le code source de brouette.py :
1 #!/usr/bin/env python
2
3 # exemple brouette.py
4
5 import pygtk
6 pygtk.require('2.0')
7 import gtk
8
9 # XPM
10 BrouettePleine_xpm = [
11 "48 48 64 1",
12 " c None",
13 ". c #DF7DCF3CC71B",
14 "X c #965875D669A6",
15 "o c #71C671C671C6",
16 "O c #A699A289A699",
17 "+ c #965892489658",
18 "@ c #8E38410330C2",
19 "# c #D75C7DF769A6",
20 "$ c #F7DECF3CC71B",
21 "% c #96588A288E38",
22 "& c #A69992489E79",
23 "* c #8E3886178E38",
24 "= c #104008200820",
25 "- c #596510401040",
26 "; c #C71B30C230C2",
27 ": c #C71B9A699658",
28 "> c #618561856185",
29 ", c #20811C712081",
30 "< c #104000000000",
31 "1 c #861720812081",
32 "2 c #DF7D4D344103",
33 "3 c #79E769A671C6",
34 "4 c #861782078617",
35 "5 c #41033CF34103",
36 "6 c #000000000000",
37 "7 c #49241C711040",
38 "8 c #492445144924",
39 "9 c #082008200820",
40 "0 c #69A618611861",
41 "q c #B6DA71C65144",
42 "w c #410330C238E3",
43 "e c #CF3CBAEAB6DA",
44 "r c #71C6451430C2",
45 "t c #EFBEDB6CD75C",
46 "y c #28A208200820",
47 "u c #186110401040",
48 "i c #596528A21861",
49 "p c #71C661855965",
50 "a c #A69996589658",
51 "s c #30C228A230C2",
52 "d c #BEFBA289AEBA",
53 "f c #596545145144",
54 "g c #30C230C230C2",
55 "h c #8E3882078617",
56 "j c #208118612081",
57 "k c #38E30C300820",
58 "l c #30C2208128A2",
59 "z c #38E328A238E3",
60 "x c #514438E34924",
61 "c c #618555555965",
62 "v c #30C2208130C2",
63 "b c #38E328A230C2",
64 "n c #28A228A228A2",
65 "m c #41032CB228A2",
66 "M c #104010401040",
67 "N c #492438E34103",
68 "B c #28A2208128A2",
69 "V c #A699596538E3",
70 "C c #30C21C711040",
71 "Z c #30C218611040",
72 "A c #965865955965",
73 "S c #618534D32081",
74 "D c #38E31C711040",
75 "F c #082000000820",
76 " ",
77 " .XoO ",
78 " +@#$%o& ",
79 " *=-;#::o+ ",
80 " >,<12#:34 ",
81 " 45671#:X3 ",
82 " +89<02qwo ",
83 "e* >,67;ro ",
84 "ty> 459@>+&& ",
85 "$2u+ > ",
87 "Oh$;ya *3d.a8j,Xe.d3g8+ ",
88 " Oh$;ka *3d$a8lz,,xxc:.e3g54 ",
89 " Oh$;kO *pd$%svbzz,sxxxxfX..&wn> ",
90 " Oh$@mO *3dthwlsslszjzxxxxxxx3:td8M4 ",
91 " Oh$@g& *3d$XNlvvvlllm,mNwxxxxxxxfa.:,B* ",
92 " Oh$@,Od.czlllllzlmmqV@V#V@fxxxxxxxf:%j5& ",
93 " Oh$1hd5lllslllCCZrV#r#:#2AxxxxxxxxxcdwM* ",
94 " OXq6c.%8vvvllZZiqqApA:mq:Xxcpcxxxxxfdc9* ",
95 " 2r<6gde3bllZZrVi7S@SV77A::qApxxxxxxfdcM ",
96 " :,q-6MN.dfmZZrrSS:#riirDSAX@Af5xxxxxfevo",
97 " +A26jguXtAZZZC7iDiCCrVVii7Cmmmxxxxxx%3g",
98 " *#16jszN..3DZZZZrCVSA2rZrV7Dmmwxxxx&en",
99 " p2yFvzssXe:fCZZCiiD7iiZDiDSSZwwxx8e*>",
100 " OA1666 >=01-kuu666> ",
112 " ,6ky& &46-10ul,66, ",
113 " Ou0<> o66y66By7=xu664 ",
115 " <> +66uv,zN666* ",
117 " 566,xxj669 ",
118 " 4666FF666> ",
119 " >966666M ",
120 " oM6668+ ",
121 " *4 ",
122 " ",
123 " "
124 ]
125
126 class ExempleBrouette:
127 # Si elle est invoquee (via le "delete_event"), cette fonction ferme l'application
128 def fermer_application(self, widget, evnmt, data=None):
129 gtk.main_quit()
130 return False
131
132 def __init__(self):
133 # Creation de la fenetre principale et connexion du signal "delete_event"
134 # a la fermeture de l'application. Notez que la fenetre principale n'aura
135 # pas de barre de titre car nous la definissons comme popup.
136 fenetre = gtk.Window(gtk.WINDOW_POPUP)
137 fenetre.connect("delete_event", self.fermer_application)
138 fenetre.set_events(fenetre.get_events() | gtk.gdk.BUTTON_PRESS_MASK)
139 fenetre.connect("button_press_event", self.fermer_application)
140 fenetre.show()
141
142 # Venons-en a la creation du pixmap et du widget gtk.Image
143 pixmap, masque = gtk.gdk.pixmap_create_from_xpm_d(
144 fenetre.window, None, BrouettePleine_xpm)
145 image = gtk.Image()
146 image.set_from_pixmap(pixmap, masque)
147 image.show()
148
149 # Pour afficher l'image, on va la placer dans un widget fixe
150 wfixe = gtk.Fixed()
151 wfixe.set_size_request(200, 200)
152 wfixe.put(image, 0, 0)
153 fenetre.add(wfixe)
154 wfixe.show()
155
156 # Ici nous masquons tout sauf l'image elle-meme
157 fenetre.shape_combine_mask(masque, 0, 0)
158
159 # On affiche la fenetre
160 fenetre.set_position(gtk.WIN_POS_CENTER_ALWAYS)
161 fenetre.show()
162
163 def main():
164 gtk.main()
165 return 0
166
167 if __name__ == "__main__":
168 ExempleBrouette()
169 main()
Pour rendre la brouette sensible à la pression d'un bouton de la souris, on a connecté son signal "button_press_event" à la méthode fermer_application() (lignes 138-139), laquelle fait se terminer le programme.