简体   繁体   English

如何在 Python 中过滤 ttk.treeview?

[英]How to filter a ttk.treeview in Python?

I have a python tkinter application that contains a ttk.treeview widget.我有一个Python tkinter包含应用程序ttk.treeview部件。

The widget displays a list of files found on a specific directory tree with a specific extension - this was trivial to build with tt.treeview widget.该小部件显示在具有特定扩展名的特定目录树上找到的文件列表 - 这对于使用tt.treeview小部件构建是微不足道的。

There is a request to enable "on-the-fly" filtering of the tree - eg, the user types in an Entry some string, and as he/she types, the tree removes elements that don't match the typed string so far.有一个请求启用树的“即时”过滤 - 例如,用户在Entry键入一些字符串,并且当他/她键入时,树删除到目前为止与键入的字符串不匹配的元素.

I was exploring the Treeview documentation, tried the detach and reattach methods but with no luck.我正在探索Treeview文档,尝试了detachreattach方法,但没有运气。

detach indeed removes the non-matched elements from the tree, but if the user hit Backspace , I can no longer iterate correctly on the tree to restore those detached elements as get_children method will not return them. detach确实从树中删除了不匹配的元素,但是如果用户点击Backspace ,我将无法在树上正确迭代以恢复那些分离的元素,因为get_children方法不会返回它们。

def filter_tree(self):
    search_by = self.search_entry.get()
    self.tree_detach_leaf_by_regex(self.current_loaded_folder, search_by, "")

def tree_detach_leaf_by_regex(self, root, regex, parent):
    if self.treeview.get_children(root):
        for child in self.treeview.get_children(root):
            self.tree_detach_leaf_by_regex(child, regex, root)
    else:
        if not re.match(regex, self.treeview.item(root)["text"]):
            self.elements_index_within_parent[root] = self.treeview.index(root)
            self.elements_parents[parent] = 1
            self.treeview.detach(root)
        else:
            self.treeview.reattach(root, parent, self.elements_index_within_parent[root])

Looking forward to read your advice.期待阅读您的建议。

To make my answer reusable by anybody, I have to tell more than directly answering your question.为了让我的答案可以被任何人重复使用,我必须说的不仅仅是直接回答你的问题。 If you directly want to see how I do to get detached items (thus without using the method get_children which cannot get detached items' id), jump to the definition of the method whose name is _columns_searcher .如果您想直接了解我如何获取分离项(因此不使用无法获取分离项的 id 的方法get_children ),请跳转到名称为_columns_searcher的方法的定义。


Introduction 简介

Let's first define some attributes.让我们首先定义一些属性。

 @property def _to_search(self): key = 'to_search' if key not in self._cache: self._cache[key] = tk.StringVar() return self._cache[key] def _set_search_entry(self): ent = ttk.Entry( self.root, # or canvas, or frame ... #... textvariable=self._to_search ) ent.grid( #... ) ent.bind( '<Return>', self._columns_searcher ) return ent @property def search_entry(self): key = 'search_entry' if key not in self._cache: self._cache[key] = self._set_search_entry() return self._cache[key]


Core answer 核心答案

What follows is the part which directly show how to re-attach user-detached items.接下来是直接展示如何重新附加用户分离项目的部分。 First note that, as the OP mentions, get_children only return ids of attached items.首先请注意,正如 OP 所提到的, get_children只返回附加项目的 ID。 Second note that the only thing you need to re-attach detached items is their id.其次要注意的是,您唯一需要重新附加分离的项目的是它们的 id。 Which implies thus to trace/save them when they are detached so as to be able to re-attach them.这意味着在它们分离时跟踪/保存它们以便能够重新连接它们。

def _brut_searcher(self, children, query):
    i_r = -1
    for item_id in children:
        text = self.tree.item(item_id)['text'] # already contains the strin-concatenation (over columns) of the row's values
        if query in text:
            i_r += 1
            self.tree.reattach(item_id, '', i_r)
        else:
            self._detached.add(item_id)
            self.tree.detach(item_id)

Note that children above contains all items , be them detached.请注意,上面的children包含所有 items ,它们是分离的。

 def _brut_searcher(self, children, query): i_r = -1 for item_id in children: text = self.tree.item(item_id)['text'] # already contains the strin-concatenation (over columns) of the row's values if query in text: i_r += 1 self.tree.reattach(item_id, '', i_r) else: self._detached.add(item_id) self.tree.detach(item_id)

From what I see, detach is almost same as delete.从我看来,分离与删除几乎相同。 row is gone and you have no access to it.行消失了,您无权访问它。 You have to make a copy of "detached" items, just id, name or more, if you have advance treeview structure, and then go over elements in both lists and sort it out.如果您有高级树视图结构,您必须制作“分离”项目的副本,只是 id、名称或更多,然后检查两个列表中的元素并对其进行排序。 Difference is that if you detach item and check it's id with "exists" function, it should return true不同之处在于,如果您分离项目并使用“exists”函数检查它的 id,它应该返回 true

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM