8.5. Example

The example program (rangewidgets.py) is a somewhat modified version of the "range controls" test from testgtk.py. It basically puts up a window with three range widgets all connected to the same adjustment, and a couple of controls for adjusting some of the parameters mentioned above and in the section on adjustments, so you can see how they affect the way these widgets work for the user. Figure 8.1 illustrates the result of running the program:

Figure 8.1 Range Widgets Example

The rangewidgets.py source code is:
 
    1   #!/usr/bin/env python
    2   
    3   # example rangewidgets.py
    4   
    5   import gtk
    6   
    7   # Convenience functions
    8   
    9   def make_menu_item(name, callback, data=None):
   10       item = gtk.GtkMenuItem(name)
   11       item.connect("activate", callback, data)
   12       item.show()
   13       return item
   14   
   15   def scale_set_default_values(scale):
   16       scale.set_update_policy(gtk.UPDATE_CONTINUOUS)
   17       scale.set_digits(1)
   18       scale.set_value_pos(gtk.POS_TOP)
   19       scale.set_draw_value(gtk.TRUE)
   20   
   21   class RangeWidgets:
   22       def cb_pos_menu_select(self, item, pos):
   23           # Set the value position on both scale widgets
   24           self.hscale.set_value_pos(pos)
   25           self.vscale.set_value_pos(pos)
   26   
   27       def cb_update_menu_select(self, item, policy):
   28           # Set the update policy for both scale widgets
   29           self.hscale.set_update_policy(policy)
   30           self.vscale.set_update_policy(policy)
   31   
   32       def cb_digits_scale(self, adj):
   33           # Set the number of decimal places to which adj->value is rounded
   34           self.hscale.set_digits(adj.value)
   35           self.vscale.set_digits(adj.value)
   36   
   37       def cb_page_size(self, get, set):
   38           # Set the page size and page increment size of the sample
   39           # adjustment to the value specified by the "Page Size" scale
   40           set.set_all(set.value, set.lower, set.upper, set.step_increment,
   41                       get.value, get.value,)
   42           # Now emit the "changed" signal to reconfigure all the widgets that
   43           # are attached to this adjustment
   44           set.emit("changed")
   45   
   46       def cb_draw_value(self, button):
   47           # Turn the value display on the scale widgets off or on depending
   48           # on the state of the checkbutton
   49           self.hscale.set_draw_value(button.active)
   50           self.vscale.set_draw_value(button.active)  
   51   
   52       # makes the sample window
   53   
   54       def __init__(self):
   55           # Standard window-creating stuff
   56           self.window = gtk.GtkWindow (gtk.WINDOW_TOPLEVEL)
   57           self.window.connect("destroy", gtk.mainquit)
   58           self.window.set_title("range controls")
   59   
   60           box1 = gtk.GtkVBox(gtk.FALSE, 0)
   61           self.window.add(box1)
   62           box1.show()
   63   
   64           box2 = gtk.GtkHBox(gtk.FALSE, 10)
   65           box2.set_border_width(10)
   66           box1.pack_start(box2, gtk.TRUE, gtk.TRUE, 0)
   67           box2.show()
   68   
   69           # value, lower, upper, step_increment, page_increment, page_size
   70           # Note that the page_size value only makes a difference for
   71           # scrollbar widgets, and the highest value you'll get is actually
   72           # (upper - page_size).
   73           adj1 = gtk.GtkAdjustment(0.0, 0.0, 101.0, 0.1, 1.0, 1.0)
   74     
   75           self.vscale = gtk.GtkVScale(adj1)
   76           scale_set_default_values(self.vscale)
   77           box2.pack_start(self.vscale, gtk.TRUE, gtk.TRUE, 0)
   78           self.vscale.show()
   79   
   80           box3 = gtk.GtkVBox(gtk.FALSE, 10)
   81           box2.pack_start(box3, gtk.TRUE, gtk.TRUE, 0)
   82           box3.show()
   83   
   84           # Reuse the same adjustment
   85           self.hscale = gtk.GtkHScale(adj1)
   86           self.hscale.set_usize(200, 30)
   87           scale_set_default_values(self.hscale)
   88           box3.pack_start(self.hscale, gtk.TRUE, gtk.TRUE, 0)
   89           self.hscale.show()
   90   
   91           # Reuse the same adjustment again
   92           scrollbar = gtk.GtkHScrollbar(adj1)
   93           # Notice how this causes the scales to always be updated
   94           # continuously when the scrollbar is moved
   95           scrollbar.set_update_policy(gtk.UPDATE_CONTINUOUS)
   96           box3.pack_start(scrollbar, gtk.TRUE, gtk.TRUE, 0)
   97           scrollbar.show()
   98   
   99           box2 = gtk.GtkHBox(gtk.FALSE, 10)
  100           box2.set_border_width(10)
  101           box1.pack_start(box2, gtk.TRUE, gtk.TRUE, 0)
  102           box2.show()
  103   
  104           # A checkbutton to control whether the value is displayed or not
  105           button = gtk.GtkCheckButton("Display value on scale widgets")
  106           button.set_active(gtk.TRUE)
  107           button.connect("toggled", self.cb_draw_value)
  108           box2.pack_start(button, gtk.TRUE, gtk.TRUE, 0)
  109           button.show()
  110     
  111           box2 = gtk.GtkHBox(gtk.FALSE, 10)
  112           box2.set_border_width(10)
  113   
  114           # An option menu to change the position of the value
  115           label = gtk.GtkLabel("Scale Value Position:")
  116           box2.pack_start(label, gtk.FALSE, gtk.FALSE, 0)
  117           label.show()
  118     
  119           opt = gtk.GtkOptionMenu()
  120           menu = gtk.GtkMenu()
  121   
  122           item = make_menu_item ("Top", self.cb_pos_menu_select, gtk.POS_TOP)
  123           menu.append(item)
  124     
  125           item = make_menu_item ("Bottom", self.cb_pos_menu_select,
  126                                  gtk.POS_BOTTOM)
  127           menu.append(item)
  128     
  129           item = make_menu_item ("Left", self.cb_pos_menu_select, gtk.POS_LEFT)
  130           menu.append(item)
  131     
  132           item = make_menu_item ("Right", self.cb_pos_menu_select, gtk.POS_RIGHT)
  133           menu.append(item)
  134     
  135           opt.set_menu(menu)
  136           box2.pack_start(opt, gtk.TRUE, gtk.TRUE, 0)
  137           opt.show()
  138   
  139           box1.pack_start(box2, gtk.TRUE, gtk.TRUE, 0)
  140           box2.show()
  141   
  142           box2 = gtk.GtkHBox(gtk.FALSE, 10)
  143           box2.set_border_width(10)
  144   
  145           # Yet another option menu, this time for the update policy of the
  146           # scale widgets
  147           label = gtk.GtkLabel("Scale Update Policy:")
  148           box2.pack_start(label, gtk.FALSE, gtk.FALSE, 0)
  149           label.show()
  150     
  151           opt = gtk.GtkOptionMenu()
  152           menu = gtk.GtkMenu()
  153     
  154           item = make_menu_item("Continuous", self.cb_update_menu_select,
  155                                 gtk.UPDATE_CONTINUOUS)
  156           menu.append(item)
  157     
  158           item = make_menu_item ("Discontinuous", self.cb_update_menu_select,
  159                                  gtk.UPDATE_DISCONTINUOUS)
  160           menu.append(item)
  161     
  162           item = make_menu_item ("Delayed", self.cb_update_menu_select,
  163                                  gtk.UPDATE_DELAYED)
  164           menu.append(item)
  165     
  166           opt.set_menu(menu)
  167           box2.pack_start(opt, gtk.TRUE, gtk.TRUE, 0)
  168           opt.show()
  169     
  170           box1.pack_start(box2, gtk.TRUE, gtk.TRUE, 0)
  171           box2.show()
  172   
  173           box2 = gtk.GtkHBox(gtk.FALSE, 10)
  174           box2.set_border_width(10)
  175     
  176           # An HScale widget for adjusting the number of digits on the
  177           # sample scales.
  178           label = gtk.GtkLabel("Scale Digits:")
  179           box2.pack_start(label, gtk.FALSE, gtk.FALSE, 0)
  180           label.show()
  181   
  182           adj2 = gtk.GtkAdjustment(1.0, 0.0, 5.0, 1.0, 1.0, 0.0)
  183           adj2.connect("value_changed", self.cb_digits_scale)
  184           scale = gtk.GtkHScale(adj2)
  185           scale.set_digits(0)
  186           box2.pack_start(scale, gtk.TRUE, gtk.TRUE, 0)
  187           scale.show()
  188   
  189           box1.pack_start(box2, gtk.TRUE, gtk.TRUE, 0)
  190           box2.show()
  191     
  192           box2 = gtk.GtkHBox(gtk.FALSE, 10)
  193           box2.set_border_width(10)
  194     
  195           # And, one last HScale widget for adjusting the page size of the
  196           # scrollbar.
  197           label = gtk.GtkLabel("Scrollbar Page Size:")
  198           box2.pack_start(label, gtk.FALSE, gtk.FALSE, 0)
  199           label.show()
  200   
  201           adj2 = gtk.GtkAdjustment(1.0, 1.0, 101.0, 1.0, 1.0, 0.0)
  202           adj2.connect("value_changed", self.cb_page_size, adj1)
  203           scale = gtk.GtkHScale(adj2)
  204           scale.set_digits(0)
  205           box2.pack_start(scale, gtk.TRUE, gtk.TRUE, 0)
  206           scale.show()
  207   
  208           box1.pack_start(box2, gtk.TRUE, gtk.TRUE, 0)
  209           box2.show()
  210   
  211           separator = gtk.GtkHSeparator()
  212           box1.pack_start(separator, gtk.FALSE, gtk.TRUE, 0)
  213           separator.show()
  214   
  215           box2 = gtk.GtkVBox(gtk.FALSE, 10)
  216           box2.set_border_width(10)
  217           box1.pack_start(box2, gtk.FALSE, gtk.TRUE, 0)
  218           box2.show()
  219   
  220           button = gtk.GtkButton("Quit")
  221           button.connect_object("clicked", gtk.mainquit, self.window)
  222           box2.pack_start(button, gtk.TRUE, gtk.TRUE, 0)
  223           button.set_flags(gtk.CAN_DEFAULT)
  224           button.grab_default()
  225           button.show()
  226           self.window.show()
  227   
  228   def main():
  229       gtk.mainloop()
  230       return 0            
  231   
  232   if __name__ == "__main__":
  233       RangeWidgets()
  234       main()

You will notice that the program does not call the connect() method for the "delete_event", but only for the "destroy" signal. This will still perform the desired operation, because an unhandled "delete_event" will result in a "destroy" signal being given to the window.