How it works...

In this example, we will use the os module, which is part of the Python Standard Library and provides a portable way of performing operating system calls.

The first use of the os module is the translation of the initial path of the tree to an absolute path, as well as initializing the nodes dictionary, which will store the correspondence between expandable items and the path of the directories they represent:

import os
import tkinter as tk
import tkinter.ttk as ttk

class App(tk.Tk):
def __init__(self, path):
# ...
abspath = os.path.abspath(path)
self.nodes = {}

For instance, os.path.abspath(".") will return the absolute version of the pathname you run the script from. We prefer this approach to using relative paths, because this saves us from any confusion when working with paths in our application.

Now, we initialize the ttk.Treeview instance with a vertical and horizontal scroll bar. The text of the icon heading will be the absolute path we calculated earlier:

        self.tree = ttk.Treeview(self)
self.tree.heading("#0", text=abspath, anchor=tk.W)
ysb = ttk.Scrollbar(self, orient=tk.VERTICAL,
command=self.tree.yview)
xsb = ttk.Scrollbar(self, orient=tk.HORIZONTAL,
command=self.tree.xview)
self.tree.configure(yscroll=ysb.set, xscroll=xsb.set)

Then, we place the widgets using the Grid geometry manager and also make the ttk.Treeview instance automatically resizable both horizontally and vertically.

After this, we bind the "<<TreeviewOpen>>" virtual event, which is generated when an expandable item is opened to the open_node() handler and call populate_node() to load the entries of the specified directory:

        self.tree.bind("<<TreeviewOpen>>", self.open_node)
self.populate_node("", abspath)

Note that the first call to this method is made with the empty string as the parent directory, which means that they do not have any parent and are displayed as top-level items.

Within the populate_node() method, we list the names of the directory entries by invoking os.listdir(). For each entry name, we perform the following actions:

  • We calculate the absolute path of the entry. On UNIX-like systems, this is achieved by concatenating the strings with a slash, but Windows uses backslashes instead. Thanks to the os.path.join() method, we can safely join the paths without worrying about platform-dependent details.
  • We insert the entry string as the last child of the indicated parent node. We always set that nodes to be initially closed, because we want to lazy load the nested items only when needed.
  • If the entry absolute path is a directory, we add the correspondence between the node and the path in the nodes attribute and insert an empty child that allows the item to be expanded:
    def populate_node(self, parent, abspath):
for entry in os.listdir(abspath):
entry_path = os.path.join(abspath, entry)
node = self.tree.insert(parent, tk.END, text=entry, open=False)
if os.path.isdir(entry_path):
self.nodes[node] = entry_path
self.tree.insert(node, tk.END)

When an expandable item is clicked, the open_node() handler retrieves the selected item by calling the focus() method of the ttk.Treeview instance.

This item identifier is used to get the absolute path previously added to the nodes attribute. To avoid raising KeyError if the node does not exist within the dictionary, we used its pop() method, which returns the second parameter as a default value—in our case, False.

If the node exists, we clear the "fake" item of the expandable node. Calling self.tree.get_children(item) returns the identifiers of the children for item, and then they are deleted by invoking self.tree.delete(children).

Once the item is cleared, we add the "real" children entries by calling populate_node() with item as their parent:

    def open_node(self, event):
item = self.tree.focus()
abspath = self.nodes.pop(item, False)
if abspath:
children = self.tree.get_children(item)
self.tree.delete(children)
self.populate_node(item, abspath)
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset