原文: http://zetcode.com/gui/pygtk/advancedwidgets/

在 PyGTK 编程教程的这一部分中,我们将介绍 PyGTK 中的一些更高级的小部件。

IconView

IconView是一个小部件,在网格中显示图标列表。

iconview.py

  1. #!/usr/bin/python
  2. # ZetCode PyGTK tutorial
  3. #
  4. # This example demonstrates the IconView widget.
  5. # It shows the contents of the currently selected
  6. # directory on the disk.
  7. #
  8. # author: jan bodnar
  9. # website: zetcode.com
  10. # last edited: February 2009
  11. import gtk
  12. import os
  13. COL_PATH = 0
  14. COL_PIXBUF = 1
  15. COL_IS_DIRECTORY = 2
  16. class PyApp(gtk.Window):
  17. def __init__(self):
  18. super(PyApp, self).__init__()
  19. self.set_size_request(650, 400)
  20. self.set_position(gtk.WIN_POS_CENTER)
  21. self.connect("destroy", gtk.main_quit)
  22. self.set_title("IconView")
  23. self.current_directory = '/'
  24. vbox = gtk.VBox(False, 0);
  25. toolbar = gtk.Toolbar()
  26. vbox.pack_start(toolbar, False, False, 0)
  27. self.upButton = gtk.ToolButton(gtk.STOCK_GO_UP);
  28. self.upButton.set_is_important(True)
  29. self.upButton.set_sensitive(False)
  30. toolbar.insert(self.upButton, -1)
  31. homeButton = gtk.ToolButton(gtk.STOCK_HOME)
  32. homeButton.set_is_important(True)
  33. toolbar.insert(homeButton, -1)
  34. self.fileIcon = self.get_icon(gtk.STOCK_FILE)
  35. self.dirIcon = self.get_icon(gtk.STOCK_DIRECTORY)
  36. sw = gtk.ScrolledWindow()
  37. sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
  38. sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
  39. vbox.pack_start(sw, True, True, 0)
  40. self.store = self.create_store()
  41. self.fill_store()
  42. iconView = gtk.IconView(self.store)
  43. iconView.set_selection_mode(gtk.SELECTION_MULTIPLE)
  44. self.upButton.connect("clicked", self.on_up_clicked)
  45. homeButton.connect("clicked", self.on_home_clicked)
  46. iconView.set_text_column(COL_PATH)
  47. iconView.set_pixbuf_column(COL_PIXBUF)
  48. iconView.connect("item-activated", self.on_item_activated)
  49. sw.add(iconView)
  50. iconView.grab_focus()
  51. self.add(vbox)
  52. self.show_all()
  53. def get_icon(self, name):
  54. theme = gtk.icon_theme_get_default()
  55. return theme.load_icon(name, 48, 0)
  56. def create_store(self):
  57. store = gtk.ListStore(str, gtk.gdk.Pixbuf, bool)
  58. store.set_sort_column_id(COL_PATH, gtk.SORT_ASCENDING)
  59. return store
  60. def fill_store(self):
  61. self.store.clear()
  62. if self.current_directory == None:
  63. return
  64. for fl in os.listdir(self.current_directory):
  65. if not fl[0] == '.':
  66. if os.path.isdir(os.path.join(self.current_directory, fl)):
  67. self.store.append([fl, self.dirIcon, True])
  68. else:
  69. self.store.append([fl, self.fileIcon, False])
  70. def on_home_clicked(self, widget):
  71. self.current_directory = os.path.realpath(os.path.expanduser('~'))
  72. self.fill_store()
  73. self.upButton.set_sensitive(True)
  74. def on_item_activated(self, widget, item):
  75. model = widget.get_model()
  76. path = model[item][COL_PATH]
  77. isDir = model[item][COL_IS_DIRECTORY]
  78. if not isDir:
  79. return
  80. self.current_directory = self.current_directory + os.path.sep + path
  81. self.fill_store()
  82. self.upButton.set_sensitive(True)
  83. def on_up_clicked(self, widget):
  84. self.current_directory = os.path.dirname(self.current_directory)
  85. self.fill_store()
  86. sensitive = True
  87. if self.current_directory == "/": sensitive = False
  88. self.upButton.set_sensitive(sensitive)
  89. PyApp()
  90. gtk.main()

本示例显示当前所选目录的图标。 它有一个工具栏和两个按钮。 向上按钮和主页按钮。 我们使用它们来浏览文件系统。

  1. self.current_directory = '/'

current_directory是目录,由IconView小部件显示。

  1. def create_store(self):
  2. store = gtk.ListStore(str, gtk.gdk.Pixbuf, bool)
  3. store.set_sort_column_id(COL_PATH, gtk.SORT_ASCENDING)
  4. return store

create_store()方法创建一个ListStore。 它是IconView小部件中使用的数据模型。 它带有三个参数。 目录名,图标的pixbuf图像和bool变量,指示我们是目录还是文件。

  1. if not fl[0] == '.':
  2. if os.path.isdir(os.path.join(self.current_directory, fl)):
  3. self.store.append([fl, self.dirIcon, True])
  4. else:
  5. self.store.append([fl, self.fileIcon, False])

fill_store()方法中,我们用数据填充列表存储。 在这里,我们找出当前路径中的所有目录。 我们排除以.开头的不可见目录。

  1. def on_home_clicked(self, widget):
  2. self.current_directory = os.path.realpath(os.path.expanduser('~'))
  3. self.fill_store()
  4. self.upButton.set_sensitive(True)

如果单击主页按钮,则主页目录将成为当前目录。 我们重新填充列表存储。 并激活向上按钮。

on_item_activated()方法中,当我们从图标视图小部件中单击一个图标时,我们会对生成的事件做出反应。

  1. model = widget.get_model()
  2. path = model[item][COL_PATH]
  3. isDir = model[item][COL_IS_DIRECTORY]
  4. if not isDir:
  5. return

我们得到激活项目的路径。 然后我们确定它是目录还是文件。 如果是文件,我们返回。

  1. self.current_directory = self.current_directory + os.path.sep + path
  2. self.fill_store()
  3. self.upButton.set_sensitive(True)

如果是目录,我们将根目录替换为当前路径,重新填充商店,然后使向上按钮敏感。

  1. def on_up_clicked(self, widget):
  2. self.current_directory = os.path.dirname(self.current_directory)
  3. self.fill_store()
  4. sensitive = True
  5. if self.current_directory == "/": sensitive = False
  6. self.upButton.set_sensitive(sensitive)

如果单击向上按钮,则将当前目录替换为其父目录。 重新填充列表存储。 如果我们在文件系统的根/目录下,则向上按钮被激活。

PyGTK 中的高级小部件 - 图1

图:IconView

ListView

在下面的示例中,我们使用TreeView小部件显示列表视图。 同样ListStore用于存储数据。

listview.py

  1. #!/usr/bin/python
  2. # ZetCode PyGTK tutorial
  3. #
  4. # This example shows a TreeView widget
  5. # in a list view mode
  6. #
  7. # author: jan bodnar
  8. # website: zetcode.com
  9. # last edited: February 2009
  10. import gtk
  11. actresses = [('jessica alba', 'pomona', '1981'), ('sigourney weaver', 'new york', '1949'),
  12. ('angelina jolie', 'los angeles', '1975'), ('natalie portman', 'jerusalem', '1981'),
  13. ('rachel weiss', 'london', '1971'), ('scarlett johansson', 'new york', '1984' )]
  14. class PyApp(gtk.Window):
  15. def __init__(self):
  16. super(PyApp, self).__init__()
  17. self.set_size_request(350, 250)
  18. self.set_position(gtk.WIN_POS_CENTER)
  19. self.connect("destroy", gtk.main_quit)
  20. self.set_title("ListView")
  21. vbox = gtk.VBox(False, 8)
  22. sw = gtk.ScrolledWindow()
  23. sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
  24. sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
  25. vbox.pack_start(sw, True, True, 0)
  26. store = self.create_model()
  27. treeView = gtk.TreeView(store)
  28. treeView.connect("row-activated", self.on_activated)
  29. treeView.set_rules_hint(True)
  30. sw.add(treeView)
  31. self.create_columns(treeView)
  32. self.statusbar = gtk.Statusbar()
  33. vbox.pack_start(self.statusbar, False, False, 0)
  34. self.add(vbox)
  35. self.show_all()
  36. def create_model(self):
  37. store = gtk.ListStore(str, str, str)
  38. for act in actresses:
  39. store.append([act[0], act[1], act[2]])
  40. return store
  41. def create_columns(self, treeView):
  42. rendererText = gtk.CellRendererText()
  43. column = gtk.TreeViewColumn("Name", rendererText, text=0)
  44. column.set_sort_column_id(0)
  45. treeView.append_column(column)
  46. rendererText = gtk.CellRendererText()
  47. column = gtk.TreeViewColumn("Place", rendererText, text=1)
  48. column.set_sort_column_id(1)
  49. treeView.append_column(column)
  50. rendererText = gtk.CellRendererText()
  51. column = gtk.TreeViewColumn("Year", rendererText, text=2)
  52. column.set_sort_column_id(2)
  53. treeView.append_column(column)
  54. def on_activated(self, widget, row, col):
  55. model = widget.get_model()
  56. text = model[row][0] + ", " + model[row][1] + ", " + model[row][2]
  57. self.statusbar.push(0, text)
  58. PyApp()
  59. gtk.main()

在我们的示例中,我们在TreeView小部件中显示了六个女演员的列表。 每行分别显示名称,出生地和出生年份。

  1. def create_model(self):
  2. store = gtk.ListStore(str, str, str)
  3. for act in actresses:
  4. store.append([act[0], act[1], act[2]])
  5. return store

create_model()方法中,我们创建列表存储。 列表存储具有三个参数。 女演员的名字,出生地和出生年份。 这是我们的TreeView小部件的数据模型。

  1. treeView = gtk.TreeView(store)
  2. treeView.connect("row-activated", self.on_activated)
  3. treeView.set_rules_hint(True)

在这里,我们以列表存储为参数创建TreeView小部件。 set_rules_hint()方法更改TreeView小部件中每第二行的背景颜色。

  1. rendererText = gtk.CellRendererText()
  2. column = gtk.TreeViewColumn("Name", rendererText, text=0)
  3. column.set_sort_column_id(0)
  4. treeView.append_column(column)

create_columns()方法中,我们向TreeView小部件中添加了三列。 上面的代码创建了一个显示女演员姓名的列。 CellRendererText从树模型的第一列检索其文本。 (文本= 0

  1. def on_activated(self, widget, row, col):
  2. model = widget.get_model()
  3. text = model[row][0] + ", " + model[row][1] + ", " + model[row][2]
  4. self.statusbar.push(0, text)

如果双击某个项目,则会在状态栏中显示整行。

PyGTK 中的高级小部件 - 图2

图:ListView

TreeView

在本章的最后一个示例中,我们使用TreeView小部件显示分层的数据树。

tree.py

  1. #!/usr/bin/python
  2. # ZetCode PyGTK tutorial
  3. #
  4. # This example shows a TreeView widget
  5. # in a tree view mode
  6. #
  7. # author: jan bodnar
  8. # website: zetcode.com
  9. # last edited: February 2009
  10. import gtk
  11. class PyApp(gtk.Window):
  12. def __init__(self):
  13. super(PyApp, self).__init__()
  14. self.set_size_request(400, 300)
  15. self.set_position(gtk.WIN_POS_CENTER)
  16. self.connect("destroy", gtk.main_quit)
  17. self.set_title("Tree")
  18. tree = gtk.TreeView()
  19. languages = gtk.TreeViewColumn()
  20. languages.set_title("Programming languages")
  21. cell = gtk.CellRendererText()
  22. languages.pack_start(cell, True)
  23. languages.add_attribute(cell, "text", 0)
  24. treestore = gtk.TreeStore(str)
  25. it = treestore.append(None, ["Scripting languages"])
  26. treestore.append(it, ["Python"])
  27. treestore.append(it, ["PHP"])
  28. treestore.append(it, ["Perl"])
  29. treestore.append(it, ["Ruby"])
  30. it = treestore.append(None, ["Compiling languages"])
  31. treestore.append(it, ["C#"])
  32. treestore.append(it, ["C++"])
  33. treestore.append(it, ["C"])
  34. treestore.append(it, ["Java"])
  35. tree.append_column(languages)
  36. tree.set_model(treestore)
  37. self.add(tree)
  38. self.show_all()
  39. PyApp()
  40. gtk.main()

这次我们使用TreeView小部件显示分层数据。

  1. tree = gtk.TreeView()

TreeView小部件已创建。

  1. languages = gtk.TreeViewColumn()
  2. languages.set_title("Programming languages")

它有一列名为"Programming languages"

  1. cell = gtk.CellRendererText()
  2. languages.pack_start(cell, True)
  3. languages.add_attribute(cell, "text", 0)

我们在TreeView小部件中显示文本数据。

  1. treestore = gtk.TreeStore(str)

要存储数据,我们使用TreeStore对象。

  1. it = treestore.append(None, ["Scripting languages"])
  2. treestore.append(it, ["Python"])
  3. treestore.append(it, ["PHP"])

我们将数据附加到树上。 TreeIter对象用于访问一行中的数据。

  1. tree.append_column(languages)

一列被附加到树上。

  1. tree.set_model(treestore)

最后,我们为树小部件设置数据模型。

PyGTK 中的高级小部件 - 图3

图:Tree

在 PyGTK 编程教程的这一章中,我们讨论的是高级 PyGTK 小部件。