9.6. Images
Prev | Chapter 9. Miscellaneous Widgets | Next

## 9.6. Images

`Images` are data structures that contain pictures. These pictures can be used in various places.

`Images` can be created from `Pixbufs`, `Pixmaps`, image files (e.g. XPM, PNG, JPEG, TIFF, etc.) and even animation files.

`Images` are created using the function:

      image = gtk.Image()

The image is then loaded using one of the following methods:

      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)

Where `pixbuf` is a `gtk.gdk.Pixbuf`; `pixmap` and `mask` are `gtk.gdk.Pixmaps`; `image` is a `gtk.gdk.Image`; `stock_id` is the name of a `gtk.StockItem`; `icon_set` is a `gtk.IconSet`; and, `animation` is a `gtk.gdk.PixbufAnimation`. the `size` argument is one of:

     ICON_SIZE_MENU
     ICON_SIZE_SMALL_TOOLBAR
     ICON_SIZE_LARGE_TOOLBAR
     ICON_SIZE_BUTTON
     ICON_SIZE_DND
     ICON_SIZE_DIALOG

The easiest way to create an image is using the `set_from_file`() method which automatically determines the image type and loads it.

The program images.py illustrates loading various image types (`goalie.gif`, `apple-red.png`, `chaos.jpg`, `important.tif`, `soccerball.gif`) into images which are then put into buttons:

Figure 9.5. Example Images in Buttons

The source code is:

        1	#!/usr/bin/env python
        2
        3	# example images.py
        4
        5	import pygtk
        6	pygtk.require('2.0')
        7	import gtk
        8
        9	class ImagesExample:
       10	    # when invoked (via signal delete_event), terminates the application.
       11	    def close_application(self, widget, event, data=None):
       12	        gtk.main_quit()
       13	        return False
       14
       15	    # is invoked when the button is clicked.  It just prints a message.
       16	    def button_clicked(self, widget, data=None):
       17	        print "button %s clicked" % data
       18
       19	    def __init__(self):
       20	        # create the main window, and attach delete_event signal to terminating
       21	        # the application
       22	        window = gtk.Window(gtk.WINDOW_TOPLEVEL)
       23	        window.connect("delete_event", self.close_application)
       24	        window.set_border_width(10)
       25	        window.show()
       26
       27	        # a horizontal box to hold the buttons
       28	        hbox = gtk.HBox()
       29	        hbox.show()
       30	        window.add(hbox)
       31
       32	        pixbufanim = gtk.gdk.PixbufAnimation("goalie.gif")
       33	        image = gtk.Image()
       34	        image.set_from_animation(pixbufanim)
       35	        image.show()
       36	        # a button to contain the image widget
       37	        button = gtk.Button()
       38	        button.add(image)
       39	        button.show()
       40	        hbox.pack_start(button)
       41	        button.connect("clicked", self.button_clicked, "1")
       42
       43	        # create several images with data from files and load images into
       44	        # buttons
       45	        image = gtk.Image()
       46	        image.set_from_file("apple-red.png")
       47	        image.show()
       48	        # a button to contain the image widget
       49	        button = gtk.Button()
       50	        button.add(image)
       51	        button.show()
       52	        hbox.pack_start(button)
       53	        button.connect("clicked", self.button_clicked, "2")
       54
       55	        image = gtk.Image()
       56	        image.set_from_file("chaos.jpg")
       57	        image.show()
       58	        # a button to contain the image widget
       59	        button = gtk.Button()
       60	        button.add(image)
       61	        button.show()
       62	        hbox.pack_start(button)
       63	        button.connect("clicked", self.button_clicked, "3")
       64
       65	        image = gtk.Image()
       66	        image.set_from_file("important.tif")
       67	        image.show()
       68	        # a button to contain the image widget
       69	        button = gtk.Button()
       70	        button.add(image)
       71	        button.show()
       72	        hbox.pack_start(button)
       73	        button.connect("clicked", self.button_clicked, "4")
       74
       75	        image = gtk.Image()
       76	        image.set_from_file("soccerball.gif")
       77	        image.show()
       78	        # a button to contain the image widget
       79	        button = gtk.Button()
       80	        button.add(image)
       81	        button.show()
       82	        hbox.pack_start(button)
       83	        button.connect("clicked", self.button_clicked, "5")
       84
       85
       86	def main():
       87	    gtk.main()
       88	    return 0
       89
       90	if __name__ == "__main__":
       91	    ImagesExample()
       92	    main()

### 9.6.1. Pixmaps

`Pixmaps` are data structures that contain pictures. These pictures can be used in various places, but most commonly as icons on the X desktop, or as cursors.

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 `gtk.gdk.Pixmap` using gtk.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.

      pixmap = gtk.gdk.pixmap_create_from_data(window, data, width, height, depth, fg, bg)

This routine is used to create a `pixmap` from `data` in memory with the color depth given by `depth`. If `depth` is -1 the color depth is derived from the depth of `window`. Each pixel uses `depth` bits of data to represent the color. `Width` and `height` are in pixels. The `window` argument must refer to a realized `gtk.gdk.Window`, since a pixmap's resources are meaningful only in the context of the screen where it is to be displayed. `fg` and `bg` are the foreground and background colors of the pixmap.

Pixmaps can be created from XPM files using:

      pixmap, mask = gtk.gdk.pixmap_create_from_xpm(window, 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. In the `pixmap_create_from_xpm`() function the first argument is a `gtk.gdk.Window` type. (Most GTK+ widgets have an underlying `gtk.gdk.Window` which can be retrieved by using the widget's window attribute.) The file, specified by `filename`, must contain an image in the XPM format and the image is loaded into the `pixmap` structure. The `mask` is a bitmap that specifies which bits of `pixmap` are opaque; it is created by the function. All other pixels are colored using the color specified by `transparent_color`. An example using this function is below.

Pixmaps can also be created from data in memory using the function:

      pixmap, mask = gtk.gdk.pixmap_create_from_xpm_d(window, transparent_color, data)

Small images can be incorporated into a program as data in the XPM format using the above function. A pixmap is created using this data, instead of reading it from a file. 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 = gtk.gdk.Pixmap(window, width, height, depth=-1)

`window` is either a `gtk.gdk.Window`. or `None`. If `window` is a `gtk.gdk.Window` then `depth` can be -1 to indicate that the depth should be determined from the window. If `window` is `None` then the `depth` must be specified.

The pixmap.py program is an example of using a pixmap in a button. Figure 9.6, “Pixmap in a Button Example” shows the result:

Figure 9.6. Pixmap in a Button Example

The source code is:

        1	#!/usr/bin/env python
        2
        3	# example pixmap.py
        4
        5	import pygtk
        6	pygtk.require('2.0')
        7	import gtk
        8
        9	# XPM data of Open-File icon
       10	xpm_data = [
       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 PixmapExample:
       34	    # when invoked (via signal delete_event), terminates the application.
       35	    def close_application(self, widget, event, data=None):
       36	        gtk.main_quit()
       37	        return False
       38
       39	    # is invoked when the button is clicked.  It just prints a message.
       40	    def button_clicked(self, widget, data=None):
       41	        print "button clicked"
       42
       43	    def __init__(self):
       44	        # create the main window, and attach delete_event signal to terminating
       45	        # the application
       46	        window = gtk.Window(gtk.WINDOW_TOPLEVEL)
       47	        window.connect("delete_event", self.close_application)
       48	        window.set_border_width(10)
       49	        window.show()
       50
       51	        # now for the pixmap from XPM data
       52	        pixmap, mask = gtk.gdk.pixmap_create_from_xpm_d(window.window,
       53	                                                        None,
       54	                                                        xpm_data)
       55
       56	        # an image widget to contain the pixmap
       57	        image = gtk.Image()
       58	        image.set_from_pixmap(pixmap, mask)
       59	        image.show()
       60
       61	        # a button to contain the image widget
       62	        button = gtk.Button()
       63	        button.add(image)
       64	        window.add(button)
       65	        button.show()
       66
       67	        button.connect("clicked", self.button_clicked)
       68
       69	def main():
       70	    gtk.main()
       71	    return 0
       72
       73	if __name__ == "__main__":
       74	    PixmapExample()
       75	    main()

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.7, “Wheelbarrow Example Shaped Window” shows the wheelbarrow over a terminal window:

Figure 9.7. Wheelbarrow Example Shaped Window

The source code for wheelbarrow.py is:

        1	#!/usr/bin/env python
        2
        3	# example wheelbarrow.py
        4
        5	import pygtk
        6	pygtk.require('2.0')
        7	import gtk
        8
        9	# XPM
       10	WheelbarrowFull_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+                  ><ipas8*                  ",
       86	"%$;=*                *3:.Xa.dfg>                ",
       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	"           OA1<jzxwwc:$d%NDZZZZCCCZCCZZCmxxfd.B ",
      101	"            3206Bwxxszx%et.eaAp77m77mmmf3&eeeg* ",
      102	"             @26MvzxNzvlbwfpdettttttttttt.c,n&  ",
      103	"             *;16=lsNwwNwgsvslbwwvccc3pcfu<o    ",
      104	"              p;<69BvwwsszslllbBlllllllu<5+     ",
      105	"              OS0y6FBlvvvzvzss,u=Blllj=54       ",
      106	"               c1-699Blvlllllu7k96MMMg4         ",
      107	"               *10y8n6FjvllllB<166668           ",
      108	"                S-kg+>666<M<996-y6n<8*          ",
      109	"                p71=4 m69996kD8Z-66698&&        ",
      110	"                &i0ycm6n4 ogk17,0<6666g         ",
      111	"                 N-k-<>     >=01-kuu666>        ",
      112	"                 ,6ky&      &46-10ul,66,        ",
      113	"                 Ou0<>       o66y<ulw<66&       ",
      114	"                  *kk5       >66By7=xu664       ",
      115	"                   <<M4      466lj<Mxu66o       ",
      116	"                   *>>       +66uv,zN666*       ",
      117	"                              566,xxj669        ",
      118	"                              4666FF666>        ",
      119	"                               >966666M         ",
      120	"                                oM6668+         ",
      121	"                                  *4            ",
      122	"                                                ",
      123	"                                                "
      124	]
      125
      126	class WheelbarrowExample:
      127	    # When invoked (via signal delete_event), terminates the application
      128	    def close_application(self, widget, event, data=None):
      129	        gtk.main_quit()
      130	        return False
      131
      132	    def __init__(self):
      133	        # Create the main window, and attach delete_event signal to terminate
      134	        # the application.  Note that the main window will not have a titlebar
      135	        # since we're making it a popup.
      136	        window = gtk.Window(gtk.WINDOW_POPUP)
      137	        window.connect("delete_event", self.close_application)
      138	        window.set_events(window.get_events() | gtk.gdk.BUTTON_PRESS_MASK)
      139	        window.connect("button_press_event", self.close_application)
      140	        window.show()
      141
      142	        # Now for the pixmap and the image widget
      143	        pixmap, mask = gtk.gdk.pixmap_create_from_xpm_d(
      144	            window.window, None, WheelbarrowFull_xpm)
      145	        image = gtk.Image()
      146	        image.set_from_pixmap(pixmap, mask)
      147	        image.show()
      148
      149	        # To display the image, we use a fixed widget to place the image
      150	        fixed = gtk.Fixed()
      151	        fixed.set_size_request(200, 200)
      152	        fixed.put(image, 0, 0)
      153	        window.add(fixed)
      154	        fixed.show()
      155
      156	        # This masks out everything except for the image itself
      157	        window.shape_combine_mask(mask, 0, 0)
      158
      159	        # show the window
      160	        window.set_position(gtk.WIN_POS_CENTER_ALWAYS)
      161	        window.show()
      162
      163	def main():
      164	    gtk.main()
      165	    return 0
      166
      167	if __name__ == "__main__":
      168	    WheelbarrowExample()
      169	    main()

To make the wheelbarrow image sensitive, we attached the "button_press_event" signal to make the program exit. Lines 138-139 make the picture sensitive to a mouse button being pressed and connect the `close_application`() method.

Prev | Up | Next
9.5. Dialogs | Home | 9.7. Rulers