I have a python tkinter
application that contains a ttk.treeview
widget.
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.
There is a request to enable "on-the-fly" filtering of the tree - e.g., 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.
I was exploring the Treeview
documentation, tried the detach
and reattach
methods but with no luck.
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.
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.
The Treeview widget items can be edited and deleted by selecting the item using tree. selection() function. Once an item is selected, we can perform certain operations to delete or edit the item.
The purpose of the ttk . Treeview widget is to present a hierarchical structure so that the user can use mouse actions to reveal or hide any part of the structure.
If we want to remove or clear all the items in a given treeview widget, then we have to first select all the items present in the treeview widget using get_children() method. Once we have selected all the treeview items programmatically, then we can delete the items using delete(item) method.
The Treeview widget is used to display a list of items with more than one feature in the form of columns. By default, the listed items in a Treeview widget can be selected multiple times, however you can disable this feature by using selectmode="browse" in the Treeview widget constructor.
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
.
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]
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. Second note that the only thing you need to re-attach detached items is their id. Which implies thus to trace/save them when they are detached so as to be able to re-attach them.
_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())
Note that children
above contains all items, be them detached.
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With