8.5. Пример виджетов регулировки диапазона

Программа rangewidgets.py создаёт окно с тремя виджетами регулировки диапазона, подключёнными к одному регулятору, и несколько виджетов управляющих параметрами регулятора, которые мы рассматривали выше в разделе "Регуляторы", теперь вы сможете посмотреть как они работают со стороны пользователя. Рисунок 8.1, “Пример виджетов регулировки диапазона” показывает результат запуска программы:

Рисунок 8.1. Пример виджетов регулировки диапазона

Range Widgets Example

Исходный код rangewidgets.py:

  1. #!/usr/bin/env python
  2. # --*-- coding:utf-8 --*--
  3. # example rangewidgets.py
  4.  
  5. import pygtk
  6. pygtk.require('2.0')
  7. import gtk
  8.  
  9. # Удобные функции
  10.  
  11. def make_menu_item(name, callback, data=None):
  12. item = gtk.MenuItem(name)
  13. item.connect("activate", callback, data)
  14. item.show()
  15. return item
  16.  
  17. def scale_set_default_values(scale):
  18. scale.set_update_policy(gtk.UPDATE_CONTINUOUS)
  19. scale.set_digits(1)
  20. scale.set_value_pos(gtk.POS_TOP)
  21. scale.set_draw_value(True)
  22.  
  23. class RangeWidgets:
  24. def cb_pos_menu_select(self, item, pos):
  25. # Устанавливает положение значения в двух виджетах Scale
  26. self.hscale.set_value_pos(pos)
  27. self.vscale.set_value_pos(pos)
  28.  
  29. def cb_update_menu_select(self, item, policy):
  30. # Устанавливает политику обновлений для двух виджетов Scale
  31. self.hscale.set_update_policy(policy)
  32. self.vscale.set_update_policy(policy)
  33.  
  34. def cb_digits_scale(self, adj):
  35. # Устанавливает количество десятичных цифр, до которых округляется adj->value.
  36. self.hscale.set_digits(int(adj.value))
  37. self.vscale.set_digits(int(adj.value))
  38.  
  39. def cb_page_size(self, get, set):
  40. # Устанавливает page_size и page_incr
  41. # регулятора в значение указанное в "Page Size" виджета Scale
  42. set.page_size = get.value
  43. set.page_incr = get.value
  44. # Теперь излучаем сигнал для перенастройки всех виджетов
  45. # которые соединены с этим регулятором
  46. set.emit("changed")
  47.  
  48. def cb_draw_value(self, button):
  49. # Устанавливает показывать value виджета Scale или нет
  50. # в зависимости от состояния переключателя
  51. self.hscale.set_draw_value(button.get_active())
  52. self.vscale.set_draw_value(button.get_active())
  53.  
  54. # Создаём окно
  55.  
  56. def __init__(self):
  57. # Стандартное создание окна
  58. self.window = gtk.Window (gtk.WINDOW_TOPLEVEL)
  59. self.window.connect("destroy", lambda w: gtk.main_quit())
  60. self.window.set_title("Управление диапазоном")
  61.  
  62. box1 = gtk.VBox(False, 0)
  63. self.window.add(box1)
  64. box1.show()
  65.  
  66. box2 = gtk.HBox(False, 10)
  67. box2.set_border_width(10)
  68. box1.pack_start(box2, True, True, 0)
  69. box2.show()
  70.  
  71. # value, lower, upper, step_increment, page_increment, page_size
  72. # Заметьте, что влияет только для виджетов Scrollbar
  73. # И максимальное значение вы можете получить по формуле
  74. # (upper - page_size).
  75. adj1 = gtk.Adjustment(0.0, 0.0, 101.0, 0.1, 1.0, 1.0)
  76.  
  77. self.vscale = gtk.VScale(adj1)
  78. scale_set_default_values(self.vscale)
  79. box2.pack_start(self.vscale, True, True, 0)
  80. self.vscale.show()
  81.  
  82. box3 = gtk.VBox(False, 10)
  83. box2.pack_start(box3, True, True, 0)
  84. box3.show()
  85.  
  86. # Повторно используем этот же регулятор
  87. self.hscale = gtk.HScale(adj1)
  88. self.hscale.set_size_request(200, 30)
  89. scale_set_default_values(self.hscale)
  90. box3.pack_start(self.hscale, True, True, 0)
  91. self.hscale.show()
  92.  
  93. # Используем этот регулятор ещё раз
  94. scrollbar = gtk.HScrollbar(adj1)
  95. # Заметьте как виджеты Scale всегда обновляются
  96. # постоянно когда передвигается Scrollbar
  97. scrollbar.set_update_policy(gtk.UPDATE_CONTINUOUS)
  98. box3.pack_start(scrollbar, True, True, 0)
  99. scrollbar.show()
  100.  
  101. box2 = gtk.HBox(False, 10)
  102. box2.set_border_width(10)
  103. box1.pack_start(box2, True, True, 0)
  104. box2.show()
  105.  
  106. # CheckButton управляющие показом значения регулятора
  107. button = gtk.CheckButton("Отображать значения шкалы")
  108. button.set_active(True)
  109. button.connect("toggled", self.cb_draw_value)
  110. box2.pack_start(button, True, True, 0)
  111. button.show()
  112.  
  113. box2 = gtk.HBox(False, 10)
  114. box2.set_border_width(10)
  115.  
  116. # Меню выбора положения на окне значения регулятора
  117. label = gtk.Label("Позиция значений шкалы:")
  118. box2.pack_start(label, False, False, 0)
  119. label.show()
  120.  
  121. opt = gtk.OptionMenu()
  122. menu = gtk.Menu()
  123.  
  124. item = make_menu_item ("Вверху", self.cb_pos_menu_select, gtk.POS_TOP)
  125. menu.append(item)
  126.  
  127. item = make_menu_item ("Внизу", self.cb_pos_menu_select,
  128. gtk.POS_BOTTOM)
  129. menu.append(item)
  130.  
  131. item = make_menu_item ("Слева", self.cb_pos_menu_select, gtk.POS_LEFT)
  132. menu.append(item)
  133.  
  134. item = make_menu_item ("Справа", self.cb_pos_menu_select, gtk.POS_RIGHT)
  135. menu.append(item)
  136.  
  137. opt.set_menu(menu)
  138. box2.pack_start(opt, True, True, 0)
  139. opt.show()
  140.  
  141. box1.pack_start(box2, True, True, 0)
  142. box2.show()
  143.  
  144. box2 = gtk.HBox(False, 10)
  145. box2.set_border_width(10)
  146.  
  147. # Ещё одно меню выбора, на этот раз для политики обновлений
  148. # виджетов Scale
  149. label = gtk.Label("Политика обновлений шкалы:")
  150. box2.pack_start(label, False, False, 0)
  151. label.show()
  152.  
  153. opt = gtk.OptionMenu()
  154. menu = gtk.Menu()
  155.  
  156. item = make_menu_item("Continuous", self.cb_update_menu_select,
  157. gtk.UPDATE_CONTINUOUS)
  158. menu.append(item)
  159.  
  160. item = make_menu_item ("Discontinuous", self.cb_update_menu_select,
  161. gtk.UPDATE_DISCONTINUOUS)
  162. menu.append(item)
  163.  
  164. item = make_menu_item ("Delayed", self.cb_update_menu_select,
  165. gtk.UPDATE_DELAYED)
  166. menu.append(item)
  167.  
  168. opt.set_menu(menu)
  169. box2.pack_start(opt, True, True, 0)
  170. opt.show()
  171.  
  172. box1.pack_start(box2, True, True, 0)
  173. box2.show()
  174.  
  175. box2 = gtk.HBox(False, 10)
  176. box2.set_border_width(10)
  177.  
  178. # Виджет HScale, для установки количества цифр
  179. # виджетов Scale.
  180. label = gtk.Label("Разрядов в шкале:")
  181. box2.pack_start(label, False, False, 0)
  182. label.show()
  183.  
  184. adj2 = gtk.Adjustment(1.0, 0.0, 5.0, 1.0, 1.0, 0.0)
  185. adj2.connect("value_changed", self.cb_digits_scale)
  186. scale = gtk.HScale(adj2)
  187. scale.set_digits(0)
  188. box2.pack_start(scale, True, True, 0)
  189. scale.show()
  190.  
  191. box1.pack_start(box2, True, True, 0)
  192. box2.show()
  193.  
  194. box2 = gtk.HBox(False, 10)
  195. box2.set_border_width(10)
  196.  
  197. # И последний виджет HScale для управления значением page_size
  198. # для виджета ScrollBar.
  199. label = gtk.Label("Размер страницы Scrollbar:")
  200. box2.pack_start(label, False, False, 0)
  201. label.show()
  202.  
  203. adj2 = gtk.Adjustment(1.0, 1.0, 101.0, 1.0, 1.0, 0.0)
  204. adj2.connect("value_changed", self.cb_page_size, adj1)
  205. scale = gtk.HScale(adj2)
  206. scale.set_digits(0)
  207. box2.pack_start(scale, True, True, 0)
  208. scale.show()
  209.  
  210. box1.pack_start(box2, True, True, 0)
  211. box2.show()
  212.  
  213. separator = gtk.HSeparator()
  214. box1.pack_start(separator, False, True, 0)
  215. separator.show()
  216.  
  217. box2 = gtk.VBox(False, 10)
  218. box2.set_border_width(10)
  219. box1.pack_start(box2, False, True, 0)
  220. box2.show()
  221.  
  222. button = gtk.Button("Выход")
  223. button.connect("clicked", lambda w: gtk.main_quit())
  224. box2.pack_start(button, True, True, 0)
  225. button.set_flags(gtk.CAN_DEFAULT)
  226. button.grab_default()
  227. button.show()
  228. self.window.show()
  229.  
  230. def main():
  231. gtk.main()
  232. return 0
  233.  
  234. if __name__ == "__main__":
  235. RangeWidgets()
  236. main()
  237.  

Вы должны заметить, что порграмма не вызывает метод connect() для "delete_event", а только для сигнала "destroy". Это выполнит желаемую операцию, так как необработанный "delete_event" выдаёт окну сигнал "destroy".