我有一个带有Gtk :: TreeModel和Gtk :: TreeModelFilter的Gtk :: TreeView。树模型是这样的:
category1
--> actual row of data
category2
--> actual row of data
我想过滤@search_entry的内容,但是如果下面的行仍然可见,我希望显示category1,如果下面的行没有可见,则要隐藏category2。我对Gtk :: TreeModelFilter #set_visible_func的理解是,您从“子模型”中获取模型和iter,以便您可以检查是否显示其子模型。每次调用Gtk :: TreeModelFilter #refilter时,都会在模型中的每个iter上调用此函数。因此我说:如果你刚给我的那个是在第一级,请获取路径,下一步,转换为过滤器模型上的相同路径,并使用是否存在新路径来测试可见性。
@store = Gtk::TreeStore.new(Gdk::Pixbuf, String, String, Menagerie::Program, TrueClass)
@tree_filter = Gtk::TreeModelFilter.new(@store)
@treeview.model = @tree_filter
# @first_time gets set to false after the model is loaded the first time
@first_time = true
@tree_filter.set_visible_func do |model, iter|
has_visible_children = true
begin
iter_path = iter.path
if iter_path.depth == 1 && @first_time != true
iter_path.down!
has_visible_children = @tree_filter.convert_child_path_to_path(iter_path) ? true : false
end
rescue => e
puts "THIS ERROR: " + e.message
end
unless @search_entry.text == ""
if [1,2].collect {|i| iter[i] =~ /#{@search_entry.text}/i }.any?
true
elsif iter[4] == true and has_visible_children
true
else
false
end
else
true
end
end
该行
has_visible_children = @tree_filter.convert_child_path_to_path(iter_path) ? true : false
导致每个iter的“THIS ERROR:stack level too deep”输出。
这里有一个无限的递归,但我不知道它在哪里发生或者我怎么能避免它。我确定我错误地考虑了这个问题,但是我几天都在没有突破的情况下进行黑客攻击。
答案 0 :(得分:1)
我对Ruby一无所知,但这个错误明显指向过多的递归迭代。每个调用都需要将上下文存储在堆栈中,从而导致 - hurray - a
堆栈溢出
:-) 添加变量以跟踪迭代级别并使用错误将其打印出来。您的数据或递归逻辑或两者都有问题。
答案 1 :(得分:1)
refilter
在每个节点上调用块。但是,返回值不会随节点一起保存,因此无论您如何操作,如果您必须向下看树,您将重复计算。
# Simplified version - returns true if search_text found in iter or any of its
# first-level children.
# Let's assume you add a method to GTK::TreeIter:
# def has_text? search_text
# self[1] =~ /#{search_text}/i or self[2] =~ /#{search_text}/i
# end
@tree_filter.set_visible_func do |model, iter|
next true if @search_entry.text.empty? # No filtering if no search text
next true if iter.path.depth == 0 # Always show root node
next true if iter.has_text? @search_entry.text
if child_iter = iter.first_child # Then we have children to check
has_visible_children = false
loop do
has_visible_children ||= child_iter.has_text? @search_entry.text
break unless child_iter.next! # returns false if no more children
end
next has_visible_children
end
next false # Not root, doesn't contain search_text, has no children
end