如何筛选使用TreeStore(而不是ListStore)的GTK树视图?

如何筛选使用TreeStore(而不是ListStore)的GTK树视图?,gtk,gtk3,pygtk,gtktreeview,Gtk,Gtk3,Pygtk,Gtktreeview,我使用Gtk.TreeView和Gtk.TreeStore作为分层数据的模型。作为一个例子,让我们把一个音乐数据库组织成三个层次:艺术家/专辑/标题。我想使用文本搜索字段筛选此树。例如,在搜索字段中键入“Five”应该沿着路径“Hank Marvin/Heartbeat/Take Five”给出一个结果 我的理解是,我需要创建一个回调函数,并使用Gtk.TreeModelFilter.set\u visible\u func()注册它。问题是,使“Take Five”的行可见不足以使其显示,我还

我使用
Gtk.TreeView
Gtk.TreeStore
作为分层数据的模型。作为一个例子,让我们把一个音乐数据库组织成三个层次:艺术家/专辑/标题。我想使用文本搜索字段筛选此树。例如,在搜索字段中键入“Five”应该沿着路径“Hank Marvin/Heartbeat/Take Five”给出一个结果

我的理解是,我需要创建一个回调函数,并使用
Gtk.TreeModelFilter.set\u visible\u func()
注册它。问题是,使“Take Five”的行可见不足以使其显示,我还必须将其所有父级也设置为可见。但是,这需要我遍历树直到它的根,并主动使每个节点沿着该路径可见,这不适合回调模式

我看到的使这种逻辑与回调模式一起工作的一种方法是检查回调函数中的整个子树,但这样每个叶节点将被检查三次。尽管如此浅薄的树可以接受性能损失,但这种攻击让我感到鸡皮疙瘩,我想避免使用它:

def可见回调(self,model,iter,_data=None):
search\u query=self.entry.get\u text().lower()
如果搜索\查询==“”:
返回真值
text=model.get_值(iter,0).lower()
如果在文本中搜索查询:
返回真值
#骇人听闻的黑客
对于范围内的i(型号:iter\u n\u儿童(iter)):
如果self.visible\u回调(model,model.iter\n子级(iter,i)):
返回真值
返回错误

在GTK中过滤树视图的预期方式是什么?(我的示例是用Python编写的,但是GTK的任何语言绑定的解决方案都可以。)

最后我提出了一个解决方案,因为我在internet上没有发现任何使用
树存储
而不是
列表存储
的treeview过滤示例,我在这里发布我的解决方案作为示例:

#/usr/bin/python
导入gi
gi.require_版本('Gtk','3.0')
gi.require_版本('Pango','1.0')
从gi.repository导入Gtk
从gi.repository导入Pango
从gi.repository导入GLib
输入信号
分层数据={
“女王”:{
“一种魔法”:[“谁想永生”,“一种魔法”],
“奇迹”:[“突破”、“丑闻”]
},
“五指致命一击”:{
“拳法”:[“拳法”、“流血”],
},
“汉克·马文”:{
“心跳”:[“Oxygene(第四部分)”,“服用五次”]
}
}
图标=[“股票持有人”、“媒体光学”、“声音”]
类TreeViewFilteringDemo(Gtk.Window):
按默认值展开\u=True
间距=10
#控制行是否应可见
COL_可视=0
#要显示的文本
COL_TEXT=1
#所需的文本权重(匹配行的粗体)
COL_重量=2
#要显示的图标
COL_图标=3
定义初始化(自):
#设置窗口
Gtk.Window.uu init_uuu(self,title=“TreeView过滤演示”)
自我设置大小请求(500500)
自我设置位置(Gtk.WindowPosition.CENTER)
self.set_可调整大小(True)
self.set_border_width(self.space)
#设置并填充树存储
self.tree_store=Gtk.TreeStore(bool,str,Pango.Weight,str)
self.add_节点(分层_数据,无,0)
#创建一些框来布置不同的控件
vbox=Gtk.Box(方向=Gtk.orientation.VERTICAL,间距=self.space)
vbox.set_齐次(False)
hbox=Gtk.Box(Gtk.Orientation.HORIZONTAL,spacing=self.spacing)
hbox.set_齐次(假)
vbox.pack_start(hbox,False,True,0)
self.add(vbox)
#用于筛选的文本条目
self.search_entry=Gtk.entry()
self.search\u entry.set\u占位符\u text(“在此处输入文本以过滤结果”)
self.search\u entry.connect(“已更改”,self.refresh\u结果)
hbox.pack\u start(self.search\u条目,真,真,0)
#添加用于控制子树显示的复选框
self.subtree_checkbox=Gtk.CheckButton(“显示匹配的子树”)
self.subtree\u checkbox.connect(“切换”,self.refresh\u结果)
hbox.pack_start(self.subtree_复选框,False,False,0)
#使用内部列进行筛选
self.filter=self.tree\u store.filter\u new()
self.filter.set\u visible\u列(self.COL\u visible)
self.treeview=Gtk.treeview(model=self.filter)
#用于图标和文本的CellRenders
icon_renderer=Gtk.CellRendererPixbuf()
text_renderer=Gtk.cellrenderText()
#将图标和文本放在一列中(否则只有
#第一列将根据其在树中的深度缩进)
col_combined=Gtk.TreeViewColumn(“图标和文本”)
col_组合。pack_开始(图标渲染器,False)
col_combined.pack_start(文本渲染器,False)
col_combined.add_属性(文本渲染器,“文本”,self.col_文本)
col\u组合。添加属性(文本渲染器,“权重”,self.col\u权重)
col_combined.add_属性(图标渲染器,“图标名称”,self.col_图标)
self.treeview.append\u列(合并列)
#滚动窗口,以防结果不适合可用空间
self.sw=Gtk.scrolled窗口()
self.sw.add(self.treeview)
vbox.pack_start(self.sw,True,True,0)
#初始化筛选
self.refresh_结果()
def添加_节点(自身、数据、父节点、级别):
“从分层数据结构创建树节点”
如果存在(数据、指令):
对于键,data.items()中的值:
child=self.tree\u store.append(父级,[True,key,Pango.Weight.NORMAL,ICONS[level])
self.add_节点(值、子级、级别+1)
其他: