简体   繁体   English

使用 tkinter Treeview 小部件显示目录内容

[英]Display directory content with tkinter Treeview widget

At the moment I am working on a program that has its own project files and inside that are like sub-files and I want to know how to use the treeview widget to display all the sub-files inside the project file, Any Ideas?目前我正在开发一个程序,它有自己的项目文件,里面有子文件,我想知道如何使用树视图小部件来显示项目文件中的所有子文件,有什么想法吗?

Thanks in advance!提前致谢!

There is an example in the source code of CPython of how to fill a Treeview recursively with the content of a directory, this is basically how it works (I have removed the event bindings and wrapped it in a class for better readability): CPython 的源代码中有一个示例,说明如何使用目录的内容递归地填充 Treeview,这基本上是它的工作原理(我已删除事件绑定并将其包装在一个类中以提高可读性):

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

class App(tk.Frame):
    def __init__(self, master, path):
        tk.Frame.__init__(self, master)
        self.tree = ttk.Treeview(self)
        ysb = ttk.Scrollbar(self, orient='vertical', command=self.tree.yview)
        xsb = ttk.Scrollbar(self, orient='horizontal', command=self.tree.xview)
        self.tree.configure(yscroll=ysb.set, xscroll=xsb.set)
        self.tree.heading('#0', text=path, anchor='w')

        abspath = os.path.abspath(path)
        root_node = self.tree.insert('', 'end', text=abspath, open=True)
        self.process_directory(root_node, abspath)

        self.tree.grid(row=0, column=0)
        ysb.grid(row=0, column=1, sticky='ns')
        xsb.grid(row=1, column=0, sticky='ew')
        self.grid()

    def process_directory(self, parent, path):
        for p in os.listdir(path):
            abspath = os.path.join(path, p)
            isdir = os.path.isdir(abspath)
            oid = self.tree.insert(parent, 'end', text=p, open=False)
            if isdir:
                self.process_directory(oid, abspath)

root = tk.Tk()
path_to_my_project = # ...
app = App(root, path=path_to_my_project)
app.mainloop()

Update: As @ArtOfWarfare mentions, it is possible to lazy populate the tree using the <<TreeviewOpen>> event.更新:正如@ArtOfWarfare 所提到的,可以使用<<TreeviewOpen>>事件延迟填充树。 To simulate the closed nodes, I've used an empty child item that is removed when a directory is opened:为了模拟关闭的节点,我使用了一个在打开目录时删除的空子项:

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


class App(object):
    def __init__(self, master, path):
        self.nodes = dict()
        frame = tk.Frame(master)
        self.tree = ttk.Treeview(frame)
        ysb = ttk.Scrollbar(frame, orient='vertical', command=self.tree.yview)
        xsb = ttk.Scrollbar(frame, orient='horizontal', command=self.tree.xview)
        self.tree.configure(yscroll=ysb.set, xscroll=xsb.set)
        self.tree.heading('#0', text='Project tree', anchor='w')

        self.tree.grid()
        ysb.grid(row=0, column=1, sticky='ns')
        xsb.grid(row=1, column=0, sticky='ew')
        frame.grid()

        abspath = os.path.abspath(path)
        self.insert_node('', abspath, abspath)
        self.tree.bind('<<TreeviewOpen>>', self.open_node)

    def insert_node(self, parent, text, abspath):
        node = self.tree.insert(parent, 'end', text=text, open=False)
        if os.path.isdir(abspath):
            self.nodes[node] = abspath
            self.tree.insert(node, 'end')

    def open_node(self, event):
        node = self.tree.focus()
        abspath = self.nodes.pop(node, None)
        if abspath:
            self.tree.delete(self.tree.get_children(node))
            for p in os.listdir(abspath):
                self.insert_node(node, p, os.path.join(abspath, p))


if __name__ == '__main__':
    root = tk.Tk()
    app = App(root, path='.')
    root.mainloop()

The imports can be changed at the second and third lines supporting Python 3.4 and above in the following manner:可以通过以下方式在支持 Python 3.4 及更高版本的第二行和第三行更改导入:

import tkinter as tk
import tkinter.ttk as ttk

Lowercase t in tkinter replacing capital T in Tkinter because Python 3.4 and above no longer recognize Tkinter; tkinter 中的小写 t 替换了 Tkinter 中的大写 T,因为 Python 3.4 及更高版本不再识别 Tkinter; eliminates an "unrecognized reference" error.消除了“无法识别的引用”错误。

Fully qualified import directives in newer Python releases are more strict about dot notation all around, therefore tkinter.ttk as ttk is required and eliminates the need for repetitive fully qualified references.较新的 Python 版本中的完全限定导入指令对点表示法更加严格,因此 tkinter.ttk 作为 ttk 是必需的,并且消除了重复完全限定引用的需要。 Caveat: one would assume that import tk.ttk would suffice, but somehow raises a reference error;警告:人们会假设 import tk.ttk 就足够了,但不知何故会引发参考错误; eliminating excessive pointers and conditional macro processing lead me to choose the above format --there are other possibilities, but this is the easiest form to use.消除过多的指针和条件宏处理使我选择了上述格式——还有其他可能性,但这是最容易使用的形式。

path_to_my_project = # ... raises an error, but is merely placeholder (still functional though) and can be changed to the following: path_to_my_project = # ... 引发错误,但只是占位符(尽管仍然有效)并且可以更改为以下内容:

path_to_my_project = "" # ...

Do remember that if running the script in Windows that a literal file path using backslashes raises and error;请记住,如果在 Windows 中运行脚本,使用反斜杠的文字文件路径会引发错误; you have to escape the backslashes in the file path url with a preceding backslash (double backslashes) like the following:您必须使用前面的反斜杠(双反斜杠)来转义文件路径 url 中的反斜杠,如下所示:

path_to_my_project = "C:\\Users\\userName\\Desktop\\projDir" #Windows file paths

Escaping backslashes in the file path with backslashes eliminates "Unicode escape character" errors where "C:\\Users" resolves to escaping the control character U in Users and this is not what we want in the first place.使用反斜杠转义文件路径中的反斜杠消除了“Unicode 转义字符”错误,其中“C:\\Users”解析为转义用户中的控制字符 U,这不是我们首先想要的。 Casting the path as a string will not work as the same errors are raised, so this:将路径转换为字符串将不起作用,因为会引发相同的错误,因此:

path_to_my_project = str("C:\Users\userName\Desktop\projDir")

...is ineffective. ……无效。

The script example (above) works with these modifications against Python 3.4 64bit run in Windows 10 64bit without issue and is very clean & solid.脚本示例(以上)适用于在 Windows 10 64 位中运行的 Python 3.4 64 位的这些修改,没有问题,并且非常干净和可靠。

I like it --runs with little effort (simple updates) without errors, warnings or unexplainable work-arounds, bs and hacks.我喜欢它 -- 毫不费力地运行(简单的更新),没有错误、警告或无法解释的变通方法、bs 和 hacks。 Thumbs up.竖起大拇指。

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

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