Jestem zwolennikiem podejścia obiektowego. Oto szablon, od którego zaczynam:
# Use Tkinter for python 2, tkinter for python 3
import tkinter as tk
class MainApplication(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.parent = parent
<create the rest of your GUI here>
if __name__ == "__main__":
root = tk.Tk()
MainApplication(root).pack(side="top", fill="both", expand=True)
root.mainloop()
Ważne rzeczy, na które należy zwrócić uwagę, to:
Nie używam importu symboli wieloznacznych. Importuję pakiet jako „tk”, co wymaga poprzedzenia wszystkich poleceń przedrostkiem tk.
. Zapobiega to zanieczyszczaniu globalnej przestrzeni nazw, a ponadto sprawia, że kod jest całkowicie oczywisty, gdy używasz klas Tkinter, klas ttk lub niektórych własnych.
Głównym zastosowaniem jest klasa . Daje to prywatną przestrzeń nazw dla wszystkich wywołań zwrotnych i funkcji prywatnych i po prostu ogólnie ułatwia organizowanie kodu. W stylu proceduralnym musisz kodować od góry do dołu, definiując funkcje przed ich użyciem itp. W przypadku tej metody nie jest to możliwe, ponieważ w rzeczywistości nie tworzy się głównego okna aż do ostatniego kroku. Wolę dziedziczyć tk.Frame
tylko dlatego, że zazwyczaj zaczynam od stworzenia ramki, ale nie jest to wcale konieczne.
Jeśli twoja aplikacja ma dodatkowe okna najwyższego poziomu, polecam uczynić każde z nich osobną klasą, dziedzicząc po tk.Toplevel
. Zapewnia to wszystkie wymienione powyżej zalety - okna są atomowe, mają własną przestrzeń nazw, a kod jest dobrze zorganizowany. Ponadto ułatwia umieszczenie każdego z nich we własnym module, gdy kod zacznie się rozrastać.
Na koniec możesz rozważyć użycie klas dla każdej większej części interfejsu. Na przykład, jeśli tworzysz aplikację z paskiem narzędzi, okienkiem nawigacji, paskiem stanu i obszarem głównym, możesz utworzyć każdą z tych klas. To sprawia, że twój główny kod jest dość mały i łatwy do zrozumienia:
class Navbar(tk.Frame): ...
class Toolbar(tk.Frame): ...
class Statusbar(tk.Frame): ...
class Main(tk.Frame): ...
class MainApplication(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.statusbar = Statusbar(self, ...)
self.toolbar = Toolbar(self, ...)
self.navbar = Navbar(self, ...)
self.main = Main(self, ...)
self.statusbar.pack(side="bottom", fill="x")
self.toolbar.pack(side="top", fill="x")
self.navbar.pack(side="left", fill="y")
self.main.pack(side="right", fill="both", expand=True)
Ponieważ wszystkie te instancje mają wspólnego rodzica, rodzic faktycznie staje się częścią „kontrolera” architektury model-widok-kontroler. Na przykład główne okno może umieścić coś na pasku stanu, wywołując self.parent.statusbar.set("Hello, world")
. Pozwala to na zdefiniowanie prostego interfejsu między komponentami, pomagając utrzymać połączenie z minimun.