GTK + 3.0:如何将Gtk.TreeStore与自定义模型项一起使用?

时间:2012-06-24 15:38:37

标签: gtk gtk3 pygobject gobject gtktreeview

我正在尝试用Python开发一个GTK应用程序,而且我真的坚持使用gtk.TreeStore的正确用法。我的主要问题:我已经解析了一些JSON,我有自己的数据结构,它基本上是一个Python列表和两种对象:一个表示项目集合(集合不能嵌套)和一个表示项目(它可能出现在列表和集合中。)

我已经熟悉TreeStore的基本用法,并设法在屏幕上正确呈现项目。我不知道如何处理树存储只能存储gobject类型的事实(此时我不确定因为我对gobject类型系统知之甚少)。 C的文档列出了以下(PixBuf除外)基本类型,它们可以插入并自动映射到Python数据类型:

  

例如,gtk_tree_store_new(3,G_TYPE_INT,G_TYPE_STRING,GDK_TYPE_PIXBUF);将创建一个新的GtkTreeStore,它有三列,分别是int,string和GdkPixbuf。

此外,它表示您可以插入任何GType。文档中的链接直接指向本段:

  

表示注册类型的唯一标识符的数值。

我对此主题的研究在此结束,Google主要查找GTK 2.x教程,而不是插入除strint等其他数据类型的内容。 问题:

  • 是否可以实现新的GType(或任何其他可以在树库中插入自定义数据的接口)以及如何操作?
    我已经尝试从GObject派生,但没有帮助。

  • 如何摆脱同时保留两个数据结构? 即我的解析结果和Treestore中的重复信息。

  • 如何处理混合内容? 在我的情况下,我有不同附加信息的集合和项目(在树视图中镜像为带或不带子项的节点)。

如果上述问题得到解决,我在处理选择时也会解决问题:很难匹配像strint这样的简单类型来匹配之前插入的项目。这样的属性必须是一个密钥,你仍然可以使用已解析的结果搜索列表,但这种结果无效。

提前谢谢!

与问题没有直接关系的其他信息:


我认为实施自定义TreeModel可能是一个可行的挑战,直到我在tutorial for GTK 2中看到这一点:

  

但是,所有这些都需要付出代价:除非您删除所有换行符,否则不太可能在不到一千行中编写有用的自定义模型。编写自定义模型并不像听起来那么困难,并且它可能值得付出努力,尤其是因为如果您需要跟踪大量数据,它将导致更加安全的代码。

这仍然有效吗?


我刚遇到http://www.pygtk.org/articles/subclassing-gobject/sub-classing-gobject-in-python.htm这有用吗?对于PyGTK 2.0来说,很多都是资源。已弃用。

1 个答案:

答案 0 :(得分:13)

问题解决了!对于遇到同样问题的其他人,我会堆积一些有用的资源和我的示例代码。如果你知道怎么做就没关系,但它确实没有记录。

完成示例代码,让TreeView填充人员并在按钮上单击打印所选人员:

from gi.repository import Gtk
from gi.repository import GObject

class Person (GObject.GObject):
    name = GObject.property(type=str)
    age = GObject.property(type=int)
    gender = GObject.property(type=bool, default=True)

    def __init__(self):
        GObject.GObject.__init__(self)

    def __repr__(self):
        s = None
        if self.get_property("gender"): s = "m"
        else: s = "f"
        return "%s, %s, %i" % (self.get_property("name"), s, self.get_property("age"))

class MyApplication (Gtk.Window):

    def __init__(self, *args, **kwargs):
        Gtk.Window.__init__(self, *args, **kwargs)
        self.set_title("Tree Display")
        self.set_size_request(400, 400)
        self.connect("destroy", Gtk.main_quit)
        self.create_widgets()
        self.insert_rows()
        self.show_all()

    def create_widgets(self):
        self.treestore = Gtk.TreeStore(Person.__gtype__)
        self.treeview = Gtk.TreeView()
        self.treeview.set_model(self.treestore)
        column = Gtk.TreeViewColumn("Person")

        cell = Gtk.CellRendererText()
        column.pack_start(cell, True)

        column.set_cell_data_func(cell, self.get_name)

        self.treeview.append_column(column)
        vbox = Gtk.VBox()
        self.add(vbox)
        vbox.pack_start(self.treeview, True, True, 0)

        button = Gtk.Button("Retrieve element")
        button.connect("clicked", self.retrieve_element)
        vbox.pack_start(button, False, False, 5)

    def get_name(self, column, cell, model, iter, data):
        cell.set_property('text', self.treestore.get_value(iter, 0).name)

    def insert_rows(self):
        for name, age, gender in [("Tom", 19, True), ("Anna", 35, False)]:
            p = Person()
            p.name = name
            p.age = age
            p.gender = gender
            self.treestore.append(None, (p,))

    def retrieve_element(self, widget):
        model, treeiter = self.treeview.get_selection().get_selected()
        if treeiter:
            print "You selected", model[treeiter][0]

if __name__ == "__main__":
    GObject.type_register(Person)
    MyApplication()
    Gtk.main()