| PyGTK Tutorial | ||
|---|---|---|
| <<< Previous | Chapter 9. Miscellaneous Widgets | Next >>> |
A pixmap which only has 2 colors is called a bitmap, and there are a few additional routines for handling this common special case.
To understand pixmaps, it would help to understand how X window system works. Under X, applications do not need to be running on the same computer that is interacting with the user. Instead, the various applications, called "clients", all communicate with a program which displays the graphics and handles the keyboard and mouse. This program which interacts directly with the user is called a "display server" or "X server." Since the communication might take place over a network, it's important to keep some information with the X server. Pixmaps, for example, are stored in the memory of the X server. This means that once pixmap values are set, they don't need to keep getting transmitted over the network; instead a command is sent to "display pixmap number XYZ here." Even if you aren't using X with GTK currently, using constructs such as Pixmaps will make your programs work acceptably under X.
To use pixmaps in PyGTK, we must first
build a GdkPixmap using GDK functions in PyGTK. Pixmaps can either be created
from in-memory data, or from data read from a file. We'll go through each
of the calls to create a pixmap.
bitmap = create_bitmap_from_data(gdkwindow, data, width, height) |
This routine is used to create a single-plane
pixmap (2 colors) from data in memory. Each bit of the data
represents whether that pixel is off or on. Width
and height are in pixels.
The gdkwindow argument must
refer to a realized GdkWindow, since a pixmap's resources are meaningful
only in the context of the screen where it is to be displayed.
pixmap, mask = create_pixmap_from_xpm(gdkwindow, transparent_color, filename) pixmap, mask = create_pixmap_from_xpm(gtkwidget, transparent_color, filename) pixmap, mask = create_pixmap_from_xpm(colormap, transparent_color, filename) |
XPM format is a readable pixmap representation
for the X Window System. It is widely used and many different utilities
are available for creating image files in this format. The create_pixmap_from_xpm()
function can be called in PyGTK with three sets of argument types as shown
above. In the first case the first argument is a GdkWindow type. (Most
GTK widgets have an underlying GdkWindow which can be retrieved by using
the widget's get_window()
method.) In the second case, the first argument is a GtkWidget which is
used by PyGTK to determine the colormap to be used to create the pixmap.
In the third case the first argument is a GdkColormap type. (Most GTK widgets
have an underlying GdkWindow which will also have a GdkColormap that can
be retrieved using the widget's get_colormap()
method.) The file specified by filename
must contain an image in that format and it is loaded into the pixmap structure.
The
mask specifies which
bits of the pixmap are opaque; it is created by the function. All other
bits are colored using the color specified by transparent_color.
An example using this follows below.
pixmap, mask = create_pixmap_from_xpm_d(gdkwindow, transparent_color, data) pixmap, mask = create_pixmap_from_xpm_d(gtkwidget, transparent_color, data) pixmap, mask = create_pixmap_from_xpm_d(colormap, transparent_color, data) |
Small images can be incorporated into
a program as data in the XPM format. A pixmap is created using this data,
instead of reading it from a file. Like the create_pixmap_from_xpm()function
there are three ways of creating a pixmap from XPM data. An example of
such data is:
xpm_data = [ "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. ", " ......... ", " ", " " ] |
The final way to create a blank pixmap
suitable for drawing operations is:
pixmap = create_pixmap(gtkwidget, width, height, depth) |
gtkwidget is either a GtkWidget that can have an underlying GdkWindow. or None. If gtkwidget is a GtkWidget then depth can be -1 to indicate that the depth should be determined from the gtkwindow. If gtkwidget is None then the depth must be specified.
Once we've created a pixmap, we can display
it as a GTK widget. We must create a GTK pixmap widget to contain the GDK
pixmap. This is done using:
gtkpixmap = GtkPixmap(gdkpixmap, mask ) |
The other pixmap widget methods are
pixmap.get_type() pixmap.set(val, mask) pixamp, mask = pixmap.get() |
The GtkPixmap set() method is used to change the pixmap that the widget is currently managing. val is a pixmap created by one of the above pixmap creation functions.
To make life a little easier a GtkPixmap
can be created directly from XPM using GtkPixmap() with
the same arguments as used for create_pixmap_from_xpm():
gtkpixmap = GtkPixmap(gdkwindow, filename, transparent_color) gtkpixmap = GtkPixmap(gtkwidget, filename, transparent_color) gtkpixmap = GtkPixmap(colormap, filename, transparent_color) |
Note: the filename and transparent_color arguments are reversed from the create_pixmap_from_xpm() function. With these convenience calls, GtkPixmap() arranges to create the pixmap and mask and then create the GtkPixmap all in one call.
The pixmap.py program is an example of using a pixmap in a button. Figure 9.5 shows the result:

1 #!/usr/bin/env python
2
3 # example pixmap.py
4
5 import gtk
6
7 # XPM data of Open-File icon
8 xpm_data = [
9 "16 16 3 1",
10 " c None",
11 ". c #000000000000",
12 "X c #FFFFFFFFFFFF",
13 " ",
14 " ...... ",
15 " .XXX.X. ",
16 " .XXX.XX. ",
17 " .XXX.XXX. ",
18 " .XXX..... ",
19 " .XXXXXXX. ",
20 " .XXXXXXX. ",
21 " .XXXXXXX. ",
22 " .XXXXXXX. ",
23 " .XXXXXXX. ",
24 " .XXXXXXX. ",
25 " .XXXXXXX. ",
26 " ......... ",
27 " ",
28 " "
29 ]
30
31 class PixmapExample:
32 # when invoked (via signal delete_event), terminates the application.
33 def close_application(self, widget, event, data=None):
34 gtk.mainquit()
35 return gtk.FALSE
36
37 # is invoked when the button is clicked. It just prints a message.
38 def button_clicked(self, widget, data=None):
39 print "button clicked"
40
41 def __init__(self):
42 # create the main window, and attach delete_event signal to terminating
43 # the application
44 window = gtk.GtkWindow(gtk.WINDOW_TOPLEVEL)
45 window.connect("delete_event", self.close_application)
46 window.set_border_width(10)
47 window.show()
48
49 # now for the pixmap from gdk
50 style = window.get_style()
51 pixmap, mask = gtk.create_pixmap_from_xpm_d(window.get_window(), 52 style.bg[gtk.STATE_NORMAL],
53 xpm_data )
54
55 # a pixmap widget to contain the pixmap
56 pixmapwid = gtk.GtkPixmap(pixmap, mask)
57 pixmapwid.show()
58
59 # a button to contain the pixmap widget
60 button = gtk.GtkButton()
61 button.add(pixmapwid)
62 window.add(button)
63 button.show()
64
65 button.connect("clicked", self.button_clicked)
66
67 def main():
68 gtk.mainloop()
69 return 0
70
71 if __name__ == "__main__":
72 PixmapExample()
73 main()
|
To load a file from an XPM data file called
icon0.xpm in the current directory, we would have created the pixmap thus
# load a pixmap from a file pixmap, mask = create_pixmap_from_xpm(window.get_window(), style.bg[STATE_NORMAL], "./icon0.xpm") pixmapwid = GtkPixmap(pixmap, mask) pixmapwid.show() window.add(pixmapwid) |
A disadvantage of using pixmaps is that the displayed object is always rectangular, regardless of the image. We would like to create desktops and applications with icons that have more natural shapes. For example, for a game interface, we would like to have round buttons to push. The way to do this is using shaped windows.
A shaped window is simply a pixmap where the background pixels are transparent. This way, when the background image is multi-colored, we don't overwrite it with a rectangular, non-matching border around our icon. The wheelbarrow.py example program displays a full wheelbarrow image on the desktop. Figure 9.6 shows the wheelbarrow over a terminal window:

1 #!/usr/bin/env python
2
3 # example-start wheelbarrow wheelbarrow.c
4
5 import gtk
6 import GDK
7
8 # XPM
9 WheelbarrowFull_xpm = [
10 "48 48 64 1",
11 " c None",
12 ". c #DF7DCF3CC71B",
13 "X c #965875D669A6",
14 "o c #71C671C671C6",
15 "O c #A699A289A699",
16 "+ c #965892489658",
17 "@ c #8E38410330C2",
18 "# c #D75C7DF769A6",
19 "$ c #F7DECF3CC71B",
20 "% c #96588A288E38",
21 "& c #A69992489E79",
22 "* c #8E3886178E38",
23 "= c #104008200820",
24 "- c #596510401040",
25 "; c #C71B30C230C2",
26 ": c #C71B9A699658",
27 "> c #618561856185",
28 ", c #20811C712081",
29 "< c #104000000000",
30 "1 c #861720812081",
31 "2 c #DF7D4D344103",
32 "3 c #79E769A671C6",
33 "4 c #861782078617",
34 "5 c #41033CF34103",
35 "6 c #000000000000",
36 "7 c #49241C711040",
37 "8 c #492445144924",
38 "9 c #082008200820",
39 "0 c #69A618611861",
40 "q c #B6DA71C65144",
41 "w c #410330C238E3",
42 "e c #CF3CBAEAB6DA",
43 "r c #71C6451430C2",
44 "t c #EFBEDB6CD75C",
45 "y c #28A208200820",
46 "u c #186110401040",
47 "i c #596528A21861",
48 "p c #71C661855965",
49 "a c #A69996589658",
50 "s c #30C228A230C2",
51 "d c #BEFBA289AEBA",
52 "f c #596545145144",
53 "g c #30C230C230C2",
54 "h c #8E3882078617",
55 "j c #208118612081",
56 "k c #38E30C300820",
57 "l c #30C2208128A2",
58 "z c #38E328A238E3",
59 "x c #514438E34924",
60 "c c #618555555965",
61 "v c #30C2208130C2",
62 "b c #38E328A230C2",
63 "n c #28A228A228A2",
64 "m c #41032CB228A2",
65 "M c #104010401040",
66 "N c #492438E34103",
67 "B c #28A2208128A2",
68 "V c #A699596538E3",
69 "C c #30C21C711040",
70 "Z c #30C218611040",
71 "A c #965865955965",
72 "S c #618534D32081",
73 "D c #38E31C711040",
74 "F c #082000000820",
75 " ",
76 " .XoO ",
77 " +@#$%o& ",
78 " *=-;#::o+ ",
79 " >,<12#:34 ",
80 " 45671#:X3 ",
81 " +89<02qwo ",
82 "e* >,67;ro ",
83 "ty> 459@>+&& ",
84 "$2u+ ><ipas8* ",
85 "%$;=* *3:.Xa.dfg> ",
86 "Oh$;ya *3d.a8j,Xe.d3g8+ ",
87 " Oh$;ka *3d$a8lz,,xxc:.e3g54 ",
88 " Oh$;kO *pd$%svbzz,sxxxxfX..&wn> ",
89 " Oh$@mO *3dthwlsslszjzxxxxxxx3:td8M4 ",
90 " Oh$@g& *3d$XNlvvvlllm,mNwxxxxxxxfa.:,B* ",
91 " Oh$@,Od.czlllllzlmmqV@V#V@fxxxxxxxf:%j5& ",
92 " Oh$1hd5lllslllCCZrV#r#:#2AxxxxxxxxxcdwM* ",
93 " OXq6c.%8vvvllZZiqqApA:mq:Xxcpcxxxxxfdc9* ",
94 " 2r<6gde3bllZZrVi7S@SV77A::qApxxxxxxfdcM ",
95 " :,q-6MN.dfmZZrrSS:#riirDSAX@Af5xxxxxfevo",
96 " +A26jguXtAZZZC7iDiCCrVVii7Cmmmxxxxxx%3g",
97 " *#16jszN..3DZZZZrCVSA2rZrV7Dmmwxxxx&en",
98 " p2yFvzssXe:fCZZCiiD7iiZDiDSSZwwxx8e*>",
99 " OA1<jzxwwc:$d%NDZZZZCCCZCCZZCmxxfd.B ",
100 " 3206Bwxxszx%et.eaAp77m77mmmf3&eeeg* ",
101 " @26MvzxNzvlbwfpdettttttttttt.c,n& ",
102 " *;16=lsNwwNwgsvslbwwvccc3pcfu<o ",
103 " p;<69BvwwsszslllbBlllllllu<5+ ",
104 " OS0y6FBlvvvzvzss,u=Blllj=54 ",
105 " c1-699Blvlllllu7k96MMMg4 ",
106 " *10y8n6FjvllllB<166668 ",
107 " S-kg+>666<M<996-y6n<8* ",
108 " p71=4 m69996kD8Z-66698&& ",
109 " &i0ycm6n4 ogk17,0<6666g ",
110 " N-k-<> >=01-kuu666> ",
111 " ,6ky& &46-10ul,66, ",
112 " Ou0<> o66y<ulw<66& ",
113 " *kk5 >66By7=xu664 ",
114 " <<M4 466lj<Mxu66o ",
115 " *>> +66uv,zN666* ",
116 " 566,xxj669 ",
117 " 4666FF666> ",
118 " >966666M ",
119 " oM6668+ ",
120 " *4 ",
121 " ",
122 " "
123 ]
124
125 class WheelbarrowExample:
126 # When invoked (via signal delete_event), terminates the application 127 def close_application(self, widget, event, data=None):
128 gtk.mainquit()
129 return gtk.FALSE
130
131 def __init__(self):
132 # Create the main window, and attach delete_event signal to terminate
133 # the application. Note that the main window will not have a titlebar
134 # since we're making it a popup.
135 window = gtk.GtkWindow(gtk.WINDOW_POPUP)
136 window.connect("delete_event", self.close_application)
137 window.set_events(window.get_events() | GDK.BUTTON_PRESS_MASK)
138 window.connect("button_press_event", self.close_application)
139 window.show()
140
141 # Now for the pixmap and the pixmap widget
142 style = window.get_style()
143 gc = style.black_gc
144 gdk_pixmap, mask = gtk.create_pixmap_from_xpm_d(
145 window.get_window(), style.bg[gtk.STATE_NORMAL],
146 WheelbarrowFull_xpm)
147 pixmap = gtk.GtkPixmap(gdk_pixmap, mask)
148 pixmap.show()
149
150 # To display the pixmap, we use a fixed widget to place the pixmap
151 fixed = gtk.GtkFixed()
152 fixed.set_usize(200, 200)
153 fixed.put(pixmap, 0, 0)
154 window.add(fixed)
155 fixed.show()
156
157 # This masks out everything except for the image itself
158 window.shape_combine_mask(mask, 0, 0)
159
160 # show the window
161 window.set_uposition(100, 200)
162 window.show()
163
164 def main():
165 gtk.mainloop()
166 return 0
167
168 if __name__ == "__main__":
169 WheelbarrowExample()
170 main()
|
To make the wheelbarrow image sensitive,
we attached the button_press_event
signal to make the program exit. Lines 137-138 make the picture sensitive
to a mouse button being pressed and connect the close_application()
method.
| <<< Previous | Home | Next >>> |
| Dialogs | Up | Rulers |