显示或填充所有驱动器的Tkinter Treeview小部件

时间:2019-02-26 15:05:40

标签: python tkinter treeview show drive

基于此答案(第一个答案的第二部分-“更新:作为@ArtOfWarfare ...”)-Tkinter: Treeview widget,我试图用所有驱动器填充Treeview,但仅填充正常工作的最后一个驱动器。有任何想法吗?我知道有一种方法可以从一开始就填充驱动器,但对于所有驱动器,我认为太多了。

import os, string
import tkinter as tk
from tkinter import ttk
from tkinter.scrolledtext import ScrolledText


class App(object):
    def __init__(self, master, path):
        splitter = tk.PanedWindow(master, orient=tk.HORIZONTAL)
        # left-side
        frame_left = tk.Frame(splitter)
        self.tree = ttk.Treeview(frame_left, show='tree')
        ysb = ttk.Scrollbar(frame_left, orient='vertical', command=self.tree.yview)
        xsb = ttk.Scrollbar(frame_left, orient='horizontal', command=self.tree.xview)
        # right-side
        frame_right = tk.Frame(splitter)
        nb = ttk.Notebook(frame_right)
        page1 = ttk.Frame(nb)
        page2 = ttk.Frame(nb)
        text = ScrolledText(page2)

        # overall layout
        splitter.add(frame_left)
        splitter.add(frame_right)
        splitter.pack(fill=tk.BOTH, expand=1)
        # left-side widget layout
        self.tree.grid(row=0, column=0, sticky='NSEW')
        ysb.grid(row=0, column=1, sticky='ns')
        xsb.grid(row=1, column=0, sticky='ew')
        # left-side frame's grid config
        frame_left.columnconfigure(0, weight=1)
        frame_left.rowconfigure(0, weight=1)
        # right-side widget layout
        text.pack(expand=1, fill="both")
        nb.add(page1, text='One')
        nb.add(page2, text='Two')
        nb.pack(expand=1, fill="both")

        # setup
        self.tree.configure(yscrollcommand=lambda f, l:self.autoscroll(ysb,f,l),
                            xscrollcommand=lambda f, l:self.autoscroll(xsb,f,l))
        # use this line instead of the previous, if you want the scroll bars to
        #always be present, but grey-out when uneeded instead of disappearing
        #self.tree.configure(yscrollcommand=ysb.set, xscrollcommand=xsb.set)
        self.tree.heading('#0', text='Project tree', anchor='w')
        self.tree.column("#0",minwidth=1080, stretch=True)

        # add default tree node
        # we create a list of dictionaries. We access them with self.nodes[i][i] -> {}
        self.nodes = [{i: {}} for i in range(len(all_drives))]
        i = 0
        for path in all_drives:
            os.chdir(os.path.join(path,'\\')) #to get '<letter>:\' all over
            abspath = os.path.abspath(path)
            self.insert_node('', abspath, abspath,i)
            i += 1
        self.tree.bind('<<TreeviewOpen>>', self.open_node)

    def autoscroll(self, sbar, first, last):
        #Hide and show scrollbar as needed.
        first, last = float(first), float(last)
        if first <= 0 and last >= 1:
            sbar.grid_remove()
        else:
            sbar.grid()
        sbar.set(first, last)

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

    def open_node(self, event):
        node = self.tree.focus() #below another method for child/parent id

        # Finding the parent id
        item_iid = self.tree.selection()[0] # child id
        parent_iid = self.tree.parent(item_iid) # parent id
        if parent_iid:
            print(self.tree.item(parent_iid)['text'])
        else:
            print(self.tree.item(item_iid)['text'])

        # We check if node/id is find in the list of keys
        keys_list = []
        for j in range(len(self.nodes)):
            keys_list.extend(iter(self.nodes[j][j].keys()))

        print(keys_list)

        for j in range(len(self.nodes)):
            if keys_list[j] == node:
                print(j)
        k = j

        abspath = self.nodes[k][k].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),k)


if __name__ == '__main__':
    root = tk.Tk()
    root.geometry("800x600")

    # get the drives - without removable
    all_drives = ['%s:' % d for d in string.ascii_uppercase if os.path.exists('%s:' % d)]

    app = App(root, path=all_drives)
    root.mainloop()

更新:我已解决了该问题,您的代码如下。

import os, string
import tkinter as tk
from tkinter import ttk
from tkinter.scrolledtext import ScrolledText


class App(object):
    def __init__(self, master, path):
        splitter = tk.PanedWindow(master, orient=tk.HORIZONTAL)
        # left-side
        frame_left = tk.Frame(splitter)
        self.tree = ttk.Treeview(frame_left, show='tree')
        ysb = ttk.Scrollbar(frame_left, orient='vertical', command=self.tree.yview)
        xsb = ttk.Scrollbar(frame_left, orient='horizontal', command=self.tree.xview)
        # right-side
        frame_right = tk.Frame(splitter)
        nb = ttk.Notebook(frame_right)
        page1 = ttk.Frame(nb)
        page2 = ttk.Frame(nb)
        text = ScrolledText(page2)

        # overall layout
        splitter.add(frame_left)
        splitter.add(frame_right)
        splitter.pack(fill=tk.BOTH, expand=1)
        # left-side widget layout
        self.tree.grid(row=0, column=0, sticky='NSEW')
        ysb.grid(row=0, column=1, sticky='ns')
        xsb.grid(row=1, column=0, sticky='ew')
        # left-side frame's grid config
        frame_left.columnconfigure(0, weight=1)
        frame_left.rowconfigure(0, weight=1)
        # right-side widget layout
        text.pack(expand=1, fill="both")
        nb.add(page1, text='One')
        nb.add(page2, text='Two')
        nb.pack(expand=1, fill="both")

        # setup
        self.tree.configure(yscrollcommand=lambda f, l:self.autoscroll(ysb,f,l),
                            xscrollcommand=lambda f, l:self.autoscroll(xsb,f,l))
        # use this line instead of the previous, if you want the scroll bars to
        #always be present, but grey-out when uneeded instead of disappearing
        #self.tree.configure(yscrollcommand=ysb.set, xscrollcommand=xsb.set)
        self.tree.heading('#0', text='Project tree', anchor='w')
        self.tree.column("#0",minwidth=1080, stretch=True)

        # ===== add default nodes to tree =====
        # we create a list of dictionaries. To access use: self.nodes[i][i] -> {}
        self.nodes = [{i: {}} for i in range(len(all_drives))]

        # create a list for nodes -> func. insert_node()
        self.node_ins = ['' for i in range(len(all_drives))]
        # create a list for nodes -> func. open_node()
        self.node_open = ['' for i in range(len(all_drives))]

        # add/insert all drives 
        i = 0
        for path in all_drives:
            os.chdir(os.path.join(path,'\\')) #to get '<letter>:\' all over
            abspath = os.path.abspath(path)
            self.insert_node('', abspath, abspath,i)
            i += 1

        self.tree.bind('<<TreeviewOpen>>', self.open_node)


    def autoscroll(self, sbar, first, last):
        #Hide and show scrollbar as needed.
        first, last = float(first), float(last)
        if first <= 0 and last >= 1:
            sbar.grid_remove()
        else:
            sbar.grid()
        sbar.set(first, last)


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


    def open_node(self, event):
        node = self.tree.focus() #below, another method for item id
        #item_id = self.tree.selection()[0] # selected item id

        k = 0              
        # We check if the node/id is find in the list of dictionaries
        for j in range(len(self.nodes)):
            if node in iter(self.nodes[j][j].keys()):
                k = list(self.nodes[j].keys())[0]

        self.node_open[k] = node
        abspath = self.nodes[k][k].pop(self.node_open[k], None)
        try:
            if abspath:
                self.tree.delete(self.tree.get_children(self.node_open[k]))
                for p in os.listdir(abspath):
                    self.insert_node(self.node_open[k], p, os.path.join(abspath, p),k)
        except OSError as e: # we can put the error into a status bar
            #print("Error:",str(e))# usually is a PermissionError
            pass


if __name__ == '__main__':
    root = tk.Tk()
    root.geometry("800x600")

    # get the drives - without removable
    all_drives = ['%s:' % d for d in string.ascii_uppercase if os.path.exists('%s:' % d)]

    app = App(root, path=all_drives)
    root.mainloop()

0 个答案:

没有答案