Tkinter:Treeview小部件

时间:2013-05-25 04:27:37

标签: python treeview tkinter tk

目前我正在开发一个程序,它有自己的项目文件,里面就像子文件,我想知道如何使用treeview小部件显示项目文件中的所有子文件,Any想法?

提前致谢!

2 个答案:

答案 0 :(得分:22)

有一个example in the source code of CPython如何以递归方式填充Treeview与目录的内容,这基本上是它的工作方式(我删除了事件绑定并将其包装在类中以提高可读性):< / p>

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

更新:正如@ArtOfWarfare所提到的,可以使用<<TreeviewOpen>>事件延迟填充树。为了模拟闭合的节点,我使用了一个在打开目录时删除的空子项:

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

答案 1 :(得分:1)

可以通过以下方式在支持Python 3.4及更高版本的第二行和第三行更改导入:

import tkinter as tk
import tkinter.ttk as ttk

tkinter中的小写t替换Tkinter中的大写字母T,因为Python 3.4及以上版本不再识别Tkinter;消除了“无法识别的参考”错误。

较新的Python版本中的完全限定的导入指令对点符号更加严格,因此需要tkinter.ttk作为ttk,并且无需重复的完全限定引用。警告:人们会认为导入tk.ttk就足够了,但不知何故会引发一个引用错误;消除过多的指针和条件宏处理导致我选择上述格式 - 还有其他可能性,但这是最简单的使用形式。

path_to_my_project =#...引发错误,但仅仅是占位符(尽管仍然有效),可以更改为以下内容:

path_to_my_project = "" # ...

请记住,如果在Windows中运行脚本,则使用反斜杠的文字路径会引发错误;你必须使用前面的反斜杠(双反斜杠)来转义文件路径url中的反斜杠,如下所示:

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

使用反斜杠转义文件路径中的反斜杠会消除“Unicode转义字符”错误,其中“C:\ Users”解析为转义用户中的控制字符U,这不是我们想要的。将路径转换为字符串将不起作用,因为引发了相同的错误,因此:

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

......无效。

脚本示例(上面)适用于针对Python 3.4 64bit在Windows 10 64bit中运行的修改而没有问题,并且非常干净&amp;固体。

我喜欢它 - 只需很少的努力(简单的更新),没有错误,警告或无法解释的解决方法,bs和hacks。竖起大拇指。