Python (GTK) : 有人能解释一下 TreeStore、Listmodel 和其他所有东西之间的区别吗?

Python (GTK) : Can someone explain the difference between TreeStore, Listmodel and all the rest?

我试图了解以下概念,但我阅读的所有文档都将所有内容捆绑在一起,但没有解释它们的真正含义,因此我不知道如何正确使用其中任何一个。如果有人能给出某种现实世界的类比,那将大有帮助。

树视图 ListView(这甚至是一件事吗?) 树店 列表存储 树模型 TreeIter

我的最终目标是从数据库中读取一组结果并将它们显示在小部件上作为可点击的项目。我已经了解了查找和检索部分,但将结果传回、显示它们并让它们更新被证明要棘手得多。

更新: 以下是从 postgreSQL 数据库读取结果并将其放入 'container' 中,从那里我可以将结果分配给输出对话框:

result = self.lookup_player(search) # this returns a result of cur.fetchall
    print result # just to make sure it returns the right things
    if len(result) > 0:  # make sure there are results
       for i in range(0, len(result)): # i used treeiter to see what it did
        treeiter=store.append([result[i][0],result[i][1],str(result[i][4])])
        print result[i][0],result[i][1],result[i][2],result[i][3],result[i][4],result[i][5],result[i][6],result[i][7],result[i][8],result[i][9],result[i][10]
    else:
       print "No players found"

我在上面使用了 ListStore,因为它看起来最合适。但也许我应该使用 Treestore,或者一个简单的列表,或者一个数组...... 很容易看出什么是字符串,或整数,浮点数,但这些 list/tree/model/stores 实际上是什么样子或做什么?

几年前我不得不放弃用 C 编写代码,因为我无法理解多态链表是什么,我迫切希望这次避免与 python 重蹈覆辙。

您对上面的 GtkListStore 代码的想法是正确的:它是一个与 SQL table 非常相似的数据存储。事实上,您会发现 GtkTreeView 基础架构的工作方式与 SQL tables 类似。您的 Gtk.ListStore() 构造函数调用直接映射到 CREATE TABLE,您的 append() 调用直接映射到 INSERT ROW.

需要注意的重要一点是,您的 GtkListStore 中的列是从左到右编号的,从 0 开始,而不是命名。这一点很重要。

GtkListStore 和 GtkTreeStore 之间的区别在于后者允许您将行作为其他行的子行,就像文件浏览器中的文件夹树一样。子行必须具有与父行相同的列格式。

GtkListStore 和 GtkTreeStore 都是 GtkTreeModel 的实现,它是一个接口。据我所知,Python 没有像接口这样的直接概念,所以只需将接口想象成一个抽象基础 class,其中没有默认实现并且必须定义每个函数。 GtkTreeModel 指定允许 GtkTreeView 在屏幕上显示数据的方法。

所以现在唯一的问题是如何将 GtkTreeView 连接到 GtkTreeModel/GtkListStore/GtkTreeStore?

您还记得 SQL,table 的每一列都有特定的数据类型。使用 GtkTreView,一列中的所有单元格都具有相同的 单元格渲染器 。单元格渲染器绘制文本、图片、复选框等,使用 GObject properties。您可能已经使用过属性:text 是 GtkLabels 上的 属性,active 是 GtkCheckButtons 上的 属性,等等。单元格渲染器的属性不仅指定了哪些数据要画,还要怎么画。

当您将 "attributes"(在函数名称中)提供给 GtkTreeViewColumn(GtkTreeView 中单个列的表示)时,您提供了调用的函数来完成提供两件事:单元格渲染器本身和属性列号对列表。

例如,假设您希望 table 模型的第 0 列提供第一列的文本。以下是创建列的方法:

renderer = Gtk.CellRendererText()            # create a text cell renderer
column = Gtk.TreeViewColumn("Column")        # create the column
column.pack_start(renderer, True)            # load the renderer...
column.add_attribute(renderer, "text", 0)    # ...and tell it to get its text from the first column of the model

现在剩下的就是将列添加到 GtkTreeView 并将 GtkListStore 设置为 GtkTreeView 的模型(set_model())。如果一切顺利,您应该会在 GtkTreeView 中看到您的数据。


GtkTreeView 不提供自己的滚动条。确保将 GtkTreeView 放在 GtkScrolledWindow 中以获取它们。

有一个 GtkListBox,但它与此完全无关。

希望这有助于解决问题!如果不明白,请随时指出您不明白的地方,我会相应地修改这个答案。


Update:回应您询问为什么 GtkTreeView 如此工作的评论,而不是管理所有数据本身并仅具有 add_row() 和 [=19 等功能=].这种设计有几个优点:

  • 让GtkTreeView自己的代码在以后更加简单,扩展性更好
  • 它允许有特殊需要的人实现他们自己的 GtkTreeModel 以用作数据存储。例如,编写足够高级或内存消耗大的程序的人可以创建一个直接与 SQL 数据库通信的 GtkTreeModel,避免在任何地方复制数据的需要。
  • 它允许 GtkTreeView 的多个实例使用相同的数据存储。
  • 它允许其他小部件使用相同的数据存储。 GtkIconView 是另一个使用 GtkTreeModel 来存储其数据的小部件(它还使用单元格渲染器来渲染数据)。