4.3. Packing Demonstration Program

    1   #!/usr/bin/env python
    2   
    3   # example packbox.py
    4   
    5   import gtk
    6   import sys, string
    7   
    8   # Helper function that makes a new hbox filled with button-labels. Arguments
    9   # for the variables we're interested are passed in to this function.  We do
   10   # not show the box, but do show everything inside.
   11   
   12   def make_box(homogeneous, spacing, expand, fill, padding):
   13   
   14       # Create a new hbox with the appropriate homogeneous
   15       # and spacing settings
   16       box = gtk.GtkHBox(homogeneous, spacing)
   17   
   18       # Create a series of buttons with the appropriate settings
   19       button = gtk.GtkButton("box.pack")
   20       box.pack_start(button, expand, fill, padding)
   21       button.show()
   22   
   23       button = gtk.GtkButton("(button,")
   24       box.pack_start(button, expand, fill, padding)
   25       button.show()
   26   
   27       # Create a button with the label depending on the value of
   28       # expand.
   29       if expand == gtk.TRUE:
   30           button = gtk.GtkButton("TRUE,")
   31       else:
   32           button = gtk.GtkButton("FALSE,")
   33   
   34       box.pack_start(button, expand, fill, padding)
   35       button.show()
   36   
   37       # This is the same as the button creation for "expand"
   38       # above, but uses the shorthand form.
   39       button = gtk.GtkButton(("FALSE,", "TRUE,")[fill==gtk.TRUE])
   40       box.pack_start(button, expand, fill, padding)
   41       button.show()
   42   
   43       padstr = "%d)" % padding
   44   
   45       button = gtk.GtkButton(padstr)
   46       box.pack_start(button, expand, fill, padding)
   47       button.show()
   48       return box
   49   
   50   class PackBox1:
   51       def delete_event(self, widget, event, data=None):
   52           gtk.mainquit()
   53           return gtk.FALSE
   54   
   55       def __init__(self, which):
   56   
   57           # Create our window
   58           self.window = gtk.GtkWindow(gtk.WINDOW_TOPLEVEL)
   59   
   60           # You should always remember to connect the delete_event signal
   61           # to the main window. This is very important for proper intuitive
   62           # behavior
   63           self.window.connect("delete_event", self.delete_event)
   64           self.window.set_border_width(10)
   65       
   66           # We create a vertical box (vbox) to pack the horizontal boxes into.
   67           # This allows us to stack the horizontal boxes filled with buttons one
   68           # on top of the other in this vbox.
   69           box1 = gtk.GtkVBox(gtk.FALSE, 0)
   70       
   71           # which example to show. These correspond to the pictures above.
   72           if which == 1:
   73               # create a new label.
   74               label = gtk.GtkLabel("GtkHBox(FALSE, 0)")
   75           
   76               # Align the label to the left side.  We'll discuss this method
   77               # and others in the section on Widget Attributes.
   78               label.set_alignment(0, 0)
   79   
   80               # Pack the label into the vertical box (vbox box1).  Remember that 
   81               # widgets added to a vbox will be packed one on top of the other in
   82               # order.
   83               box1.pack_start(label, gtk.FALSE, gtk.FALSE, 0)
   84           
   85               # Show the label
   86               label.show()
   87           
   88               # Call our make box function - homogeneous = FALSE, spacing = 0,
   89               # expand = FALSE, fill = FALSE, padding = 0
   90               box2 = make_box(gtk.FALSE, 0, gtk.FALSE, gtk.FALSE, 0)
   91               box1.pack_start(box2, gtk.FALSE, gtk.FALSE, 0)
   92               box2.show()
   93   
   94               # Call our make box function - homogeneous = FALSE, spacing = 0,
   95               # expand = TRUE, fill = FALSE, padding = 0
   96               box2 = make_box(gtk.FALSE, 0, gtk.TRUE, gtk.FALSE, 0)
   97               box1.pack_start(box2, gtk.FALSE, gtk.FALSE, 0)
   98               box2.show()
   99           
  100               # Args are: homogeneous, spacing, expand, fill, padding
  101               box2 = make_box(gtk.FALSE, 0, gtk.TRUE, gtk.TRUE, 0)
  102               box1.pack_start(box2, gtk.FALSE, gtk.FALSE, 0)
  103               box2.show()
  104           
  105               # Creates a separator, we'll learn more about these later, 
  106               # but they are quite simple.
  107               separator = gtk.GtkHSeparator()
  108           
  109               # Pack the separator into the vbox. Remember each of these
  110               # widgets is being packed into a vbox, so they'll be stacked
  111               # vertically.
  112               box1.pack_start(separator, gtk.FALSE, gtk.TRUE, 5)
  113               separator.show()
  114           
  115               # Create another new label, and show it.
  116               label = gtk.GtkLabel("GtkHBox(TRUE, 0)")
  117               label.set_alignment(0, 0)
  118               box1.pack_start(label, gtk.FALSE, gtk.FALSE, 0)
  119               label.show()
  120           
  121               # Args are: homogeneous, spacing, expand, fill, padding
  122               box2 = make_box(gtk.TRUE, 0, gtk.TRUE, gtk.FALSE, 0)
  123               box1.pack_start(box2, gtk.FALSE, gtk.FALSE, 0)
  124               box2.show()
  125           
  126               # Args are: homogeneous, spacing, expand, fill, padding
  127               box2 = make_box(gtk.TRUE, 0, gtk.TRUE, gtk.TRUE, 0)
  128               box1.pack_start(box2, gtk.FALSE, gtk.FALSE, 0)
  129               box2.show()
  130           
  131               # Another new separator.
  132               separator = gtk.GtkHSeparator()
  133               # The last 3 arguments to pack_start are:
  134               # expand, fill, padding.
  135               box1.pack_start(separator, gtk.FALSE, gtk.TRUE, 5)
  136               separator.show()
  137           elif which == 2:
  138               # Create a new label, remember box1 is a vbox as created 
  139               # near the beginning of __init__()
  140               label = gtk.GtkLabel("GtkHBox(FALSE, 10)")
  141               label.set_alignment( 0, 0)
  142               box1.pack_start(label, gtk.FALSE, gtk.FALSE, 0)
  143               label.show()
  144           
  145               # Args are: homogeneous, spacing, expand, fill, padding
  146               box2 = make_box(gtk.FALSE, 10, gtk.TRUE, gtk.FALSE, 0)
  147               box1.pack_start(box2, gtk.FALSE, gtk.FALSE, 0)
  148               box2.show()
  149           
  150               # Args are: homogeneous, spacing, expand, fill, padding
  151               box2 = make_box(gtk.FALSE, 10, gtk.TRUE, gtk.TRUE, 0)
  152               box1.pack_start(box2, gtk.FALSE, gtk.FALSE, 0)
  153               box2.show()
  154           
  155               separator = gtk.GtkHSeparator()
  156               # The last 3 arguments to pack_start are:
  157               # expand, fill, padding.
  158               box1.pack_start(separator, gtk.FALSE, gtk.TRUE, 5)
  159               separator.show()
  160           
  161               label = gtk.GtkLabel("GtkHBox(FALSE, 0)")
  162               label.set_alignment(0, 0)
  163               box1.pack_start(label, gtk.FALSE, gtk.FALSE, 0)
  164               label.show()
  165           
  166               # Args are: homogeneous, spacing, expand, fill, padding
  167               box2 = make_box(gtk.FALSE, 0, gtk.TRUE, gtk.FALSE, 10)
  168               box1.pack_start(box2, gtk.FALSE, gtk.FALSE, 0)
  169               box2.show()
  170           
  171               # Args are: homogeneous, spacing, expand, fill, padding
  172               box2 = make_box(gtk.FALSE, 0, gtk.TRUE, gtk.TRUE, 10)
  173               box1.pack_start(box2, gtk.FALSE, gtk.FALSE, 0)
  174               box2.show()
  175           
  176               separator = gtk.GtkHSeparator()
  177               # The last 3 arguments to pack_start are:
  178               # expand, fill, padding.
  179               box1.pack_start(separator, gtk.FALSE, gtk.TRUE, 5)
  180               separator.show()
  181   
  182           elif which == 3:
  183   
  184               # This demonstrates the ability to use pack_end() to
  185               # right justify widgets. First, we create a new box as before.
  186               box2 = make_box(gtk.FALSE, 0, gtk.FALSE, gtk.FALSE, 0)
  187   
  188               # Create the label that will be put at the end.
  189               label = gtk.GtkLabel("end")
  190               # Pack it using pack_end(), so it is put on the right
  191               # side of the hbox created in the make_box() call.
  192               box2.pack_end(label, gtk.FALSE, gtk.FALSE, 0)
  193               # Show the label.
  194               label.show()
  195           
  196               # Pack box2 into box1
  197               box1.pack_start(box2, gtk.FALSE, gtk.FALSE, 0)
  198               box2.show()
  199           
  200               # A separator for the bottom.
  201               separator = gtk.GtkHSeparator()
  202               
  203               # This explicitly sets the separator to 400 pixels wide by 5
  204               # pixels high. This is so the hbox we created will also be 400
  205               # pixels wide, and the "end" label will be separated from the
  206               # other labels in the hbox. Otherwise, all the widgets in the
  207               # hbox would be packed as close together as possible.
  208               separator.set_usize(400, 5)
  209               # pack the separator into the vbox (box1) created near the start 
  210               # of __init__()
  211               box1.pack_start(separator, gtk.FALSE, gtk.TRUE, 5)
  212               separator.show()
  213       
  214           # Create another new hbox.. remember we can use as many as we need!
  215           quitbox = gtk.GtkHBox(gtk.FALSE, 0)
  216       
  217           # Our quit button.
  218           button = gtk.GtkButton("Quit")
  219       
  220           # Setup the signal to terminate the program when the button is clicked
  221           button.connect_object("clicked", gtk.mainquit, self.window)
  222           # Pack the button into the quitbox.
  223           # The last 3 arguments to pack_start are:
  224           # expand, fill, padding.
  225           quitbox.pack_start(button, gtk.TRUE, gtk.FALSE, 0)
  226           # pack the quitbox into the vbox (box1)
  227           box1.pack_start(quitbox, gtk.FALSE, gtk.FALSE, 0)
  228       
  229           # Pack the vbox (box1) which now contains all our widgets, into the
  230           # main window.
  231           self.window.add(box1)
  232       
  233           # And show everything left
  234           button.show()
  235           quitbox.show()
  236       
  237           box1.show()
  238           # Showing the window last so everything pops up at once.
  239           self.window.show()
  240   
  241   def main():
  242       # And of course, our main loop.
  243       gtk.mainloop()
  244       # Control returns here when mainquit() is called
  245       return 0         
  246   
  247   if __name__ =="__main__":
  248       if len(sys.argv) != 2:
  249           sys.stderr.write("usage: packbox.py num, where num is 1, 2, or 3.\n")
  250           sys.exit(1)
  251       PackBox1(string.atoi(sys.argv[1]))
  252       main()
A brief tour of the packbox.py code starts with lines 12-48 which define a helper function make_box() that creates a horizontal box and populates it with buttons according to the specified parameters. A reference to the horizontal box is returned.

Lines 55-239 define the PackBox1 class initialization method __init__() that creates a window and a child veritcal box that is populated with a different widget arrangement depending on the argument passed to it. If a 1 is passed, lines 73-136 create a window displaying the five unique packing arrangments that are available when varying the homogeneous, expand and fill parameters. If a 2 is passed, lines 138-180 create a window displaying the various combinations of fill with spacing and padding. Finally, if a 3 is passed, lines 186-212 create a window displaying the use of the pack_start() method to left justfy the buttons and pack_end() method to right justify a label. Lines 215-235 create a horizontal box containing a button that is packed into the vertical box. The button "clicked" signal is connected to the PyGTK mainquit() function to terminate the program.

Lines 248-250 check the command line arguments and exit the program using the sys.exit() function if there isn't exactly one argument Line 251 creates a PackBox1 instance. Line 252 invokes the main() function to start the GTK event processing loop.

In this example program, the references to the various widgets (except the window) are not saved in the object instance attributes because they are not needed later.