如何在 Python 中过滤 ttk.treeview



我有一个python tkinter应用程序,其中包含一个ttk.treeview小部件。

该小部件显示在具有特定扩展名的特定目录树上找到的文件列表 - 使用tt.treeview小部件构建这是微不足道的。

有一个请求启用树的"动态"过滤 - 例如,用户键入Entry某个字符串,并且当他/她键入时,树会删除到目前为止与类型字符串不匹配的元素。

我正在探索Treeview文档,尝试了detachreattach方法,但没有运气。

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])

期待阅读您的建议。

为了让我的答案可以被任何人重复使用,我必须讲述的不仅仅是直接回答你的问题。如果您直接想了解我如何获取分离的项目(因此不使用无法获取分离项目id的方法get_children(,请跳转到名称为_columns_searcher的方法的定义。


介绍

让我们首先定义一些属性。

@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]


核心答案

接下来是直接显示如何重新附加用户分离的项目的部分。首先请注意,正如 OP 所提到的,get_children只返回附加项的 ID。第二请注意,重新附加分离的项目唯一需要的是它们的 ID。这意味着在它们分离时跟踪/保存它们,以便能够重新连接它们。

_detached = set()
def _columns_searcher(self, event):
    #              originally a set            returns a tuple
    children = list(self._detached) + list(self.tree.get_children())
    self._detached = set()
    query = self._to_search.get()
    self._brut_searcher(children, query.lower())

请注意,上面的children包含所有项目,无论是分离的。

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)

据我所知,分离几乎与删除相同。行消失了,您无法访问它。如果你有高级树视图结构,你必须复制"分离"的项目,只是id,name或更多,然后检查两个列表中的元素并对其进行排序。不同之处在于,如果您分离项目并使用"存在"函数检查它的 id,它应该返回 true

最新更新