2013-05-25 18 views
9

W tej chwili pracuję nad programem, który ma własne pliki projektu i wewnątrz, które są podobne do plików podrzędnych i chcę wiedzieć, jak korzystać z widżetu widoku drzewa, aby wyświetlić wszystkie pliki podrzędne wewnątrz plik projektu, jakieś pomysły?Tkinter: Widżet drzewa

Z góry dzięki!

+0

Ten projekt opensource może ci bardzo pomóc: https: // github.com/talcs/tals_python_task_diary – SomethingSomething

Odpowiedz

17

Jest example in the source code of CPython sposobu wypełnienia katalogów rekurencyjnie z treścią katalogu, to jest w zasadzie jak to działa (usunąłem powiązania zdarzeń i owinął je w klasie dla lepszej czytelności):

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

Aktualizacja: Jak wspomina @ArtOfWarfare, możliwe jest leniwe wypełnić drzewo używając zdarzenie <<TreeviewOpen>>. Aby symulować zamkniętych węzłów Użyłem pusty element podrzędny, który jest usuwany, gdy katalog jest otwarty:

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

Zakładając, że pytający naprawdę mapował system plików, to jest dobre rozwiązanie. –

+0

@DonalFellows - To jest dobra odpowiedź, bez względu na to, co pytający naprawdę próbował zrobić, ponieważ naprawdę odpowiada na to, o co prosi. Dokładnie tego chciałem (przykład Treeview - dopiero zaczynam od tk/ttk i potrzebuję zobaczyć kilka innych przykładów, zanim będę gotowy do samodzielnego pisania od początku.) – ArtOfWarfare

+0

Ponad dwa lata później mają na to inną myśl - czy nie będzie to naprawdę nieefektywne? Zamierzasz zapełniać katalogi, których użytkownik nigdy nie będzie mógł rozwinąć. Na pewno istnieje sposób na odroczenie wywoływania 'process_directory', dopóki użytkownik faktycznie go nie otworzy? – ArtOfWarfare

1

Import może być zmieniony w drugiej i trzeciej linii pomocniczych Python 3.4 i powyżej w następujący sposób :

import tkinter as tk 
import tkinter.ttk as ttk 

Małe litery T w Tkinter zastępując litera T w Tkinter ponieważ Pythonie 3.4, powyżej już rozpoznać Tkinter; eliminuje błąd "nierozpoznanego odniesienia".

W pełni kwalifikowane dyrektywy dotyczące importu w nowszych wydaniach w języku Python są bardziej rygorystyczne w zakresie notacji kropkowej, dlatego tkinter.ttk jako ttk jest wymagany i eliminuje potrzebę powtarzania w pełni kwalifikowanych referencji. Zastrzeżenie: można by zakładać, że import tk.ttk wystarczy, ale w jakiś sposób podnosi błąd odniesienia; wyeliminowanie nadmiernych wskaźników i warunkowe przetwarzanie makr doprowadziło mnie do wybrania powyższego formatu - istnieją inne możliwości, ale jest to najłatwiejsza w użyciu forma.

path_to_my_project = # ... zgłasza błąd, ale jest jedynie zastępczym (choć nadal funkcjonalny) i może zostać zmieniony na następujący:

path_to_my_project = "" # ... 

Czy pamiętać, że jeśli uruchomienie skryptu w systemie Windows, który dosłownym ścieżka pliku za pomocą backslashes podnosi i błąd; musisz uciec backslashy w adresie URL ścieżka pliku z poprzedniego backslash (podwójne backslashe) tak:

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

Uciekając backslashy w ścieżce pliku z ukośniki eliminuje „charakter ucieczki Unicode” błędy gdzie „C: \ Użytkownicy "postanawiają uchylić się przed znakiem kontrolnym U w Użytkownicy i to nie jest to, czego chcemy w pierwszej kolejności. Przesyłanie ścieżki jako łańcucha znaków nie działa, ponieważ zgłaszane są te same błędy, więc:

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

... jest nieskuteczny.

Przykład skryptu (powyżej) działa z tymi modyfikacjami przeciwko Pythonowi 3.4 64-bitowemu uruchamianemu w systemie Windows 10 64bit bez problemu i jest bardzo czysty & solidny.

Bardzo mi się podoba --runs przy niewielkim wysiłku (proste aktualizacje) bez błędów, ostrzeżeń lub niewyjaśnionych obejść, bs i hacków. Kciuki w górę.