GTK+ 3.0:如何将 Gtk.TreeStore 与自定义模型项一起使用?
Posted
技术标签:
【中文标题】GTK+ 3.0:如何将 Gtk.TreeStore 与自定义模型项一起使用?【英文标题】:GTK+ 3.0: How to use a Gtk.TreeStore with custom model items? 【发布时间】:2012-06-26 01:59:57 【问题描述】:我正在尝试用 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 教程,除了 str
和 int
等之外,没有任何关于插入其他数据类型的内容。
问题:
是否可以实现新的 GType(或任何其他可以在树存储中插入自定义数据的接口)以及如何实现?
我已经尝试从 GObject
派生,但没有帮助。
如何避免同时保留两个数据结构? 即我的解析结果和Treestore中的重复信息。
如何处理混合内容? 就我而言,我有具有不同附加信息的集合和项目(在树视图中镜像为有或没有子节点的节点)。
如果上述问题得到解决,我在处理选择时也摆脱了这个问题:很难匹配像str
或int
这样的简单类型来匹配我之前插入的项目。这样的属性必须是一个键,你仍然会搜索具有解析结果的列表,这是无效的。
提前谢谢你!
与问题没有直接关系的其他信息:
我认为实现自定义TreeModel
可能是一个可行的挑战,直到我在tutorial for GTK 2 中读到此内容:
但是,所有这些都是有代价的:您不可能在不到一千行的时间内编写出有用的自定义模型,除非您去掉所有换行符。编写自定义模型并不像听起来那么困难,而且值得付出努力,尤其是因为如果您有大量数据需要跟踪,它会产生更清晰的代码。
这仍然有效吗?
我刚刚遇到http://www.pygtk.org/articles/subclassing-gobject/sub-classing-gobject-in-python.htm 这有帮助吗?与 PyGTK 2.0 一样多的资源。 已弃用。
【问题讨论】:
请注意,一千行 C 语言更像是 200 行 Python。 我已经实现了一个不到 100 行的自定义 Treemodel。我认为主要问题可能是性能,因为原来的c函数被python函数取代了。 有这个相关的问题。在其评论中,有一个指向自定义实现的 python 3 Treemodel 接口示例的链接。 ***.com/questions/32611820/… 【参考方案1】:问题解决了!对于遇到同样问题的其他人,我将收集一些有用的资源和我的示例代码。如果你知道怎么做也没关系,但它确实没有记录。
正确派生自 GObject
的属性:http://python-gtk-3-tutorial.readthedocs.org/en/latest/objects.html
如何欺骗 TreeView 接受 CellRendererText
的自定义值,包括用于实现传递给 set_cell_data_func
的函数的有用 sn-p(需要适应 TreeView
)How to make GtkListStore store object attribute in a row?
关于 TreeViews 的一般良好文档http://python-gtk-3-tutorial.readthedocs.org/en/latest/treeview.html
完整的示例代码,用于在 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()
【讨论】:
对于 python3 用户:更改打印语句并添加行import gi
和 gi.require_version("Gtk","3.0")
就可以了。
很多感谢这个答案,它让我的树包含人类可读的部分以及数据库 ID,我知道这是一个非常古老的答案,购买你能解释一下Person
中的姓名/年龄/性别GObject.Property
和insert_rows()
后面设置的对象成员变量之间的关系吗?
@Kingsley 是的,已经有一段时间了,我不记得所有细节了。从它的外观来看,GObject
的构造函数可能在幕后做了一些魔术,将类体中的属性定义转换为字段。或者也许 GObject 提供了一个合适的getattr 方法。很抱歉我无法深入了解细节?以上是关于GTK+ 3.0:如何将 Gtk.TreeStore 与自定义模型项一起使用?的主要内容,如果未能解决你的问题,请参考以下文章