Poniżej przedstawiono ogólną strukturę mojego typowego programu tkinter w języku Python.
def funA():
def funA1():
def funA12():
# stuff
def funA2():
# stuff
def funB():
def funB1():
# stuff
def funB2():
# stuff
def funC():
def funC1():
# stuff
def funC2():
# stuff
root = tk.Tk()
button1 = tk.Button(root, command=funA)
button1.pack()
button2 = tk.Button(root, command=funB)
button2.pack()
button3 = tk.Button(root, command=funC)
button3.pack()
funA
funB
i funC
przywoła innyToplevel
okno z widżetami, gdy użytkownik kliknie przycisk 1, 2, 3.
Zastanawiam się, czy to jest właściwy sposób na napisanie programu tkinter w Pythonie? Jasne, zadziała, nawet jeśli napiszę w ten sposób, ale czy to najlepszy sposób? Brzmi głupio, ale kiedy widzę kody napisane przez innych ludzi, ich kod nie jest pomieszany z wieloma funkcjami i przeważnie mają klasy.
Czy jest jakaś konkretna struktura, której powinniśmy przestrzegać jako dobrej praktyki? Jak powinienem zaplanować przed rozpoczęciem pisania programu w Pythonie?
Wiem, że nie ma czegoś takiego jak najlepsze praktyki w programowaniu i też o to nie proszę. Chcę tylko kilku rad i wyjaśnień, które utrzymają mnie we właściwym kierunku, gdy sam uczę się Pythona.
Odpowiedzi:
Jestem zwolennikiem podejścia obiektowego. Oto szablon, od którego zaczynam:
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:
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.źródło
parent
, chyba że zamierzasz go później użyć. Nie zapisałem go, ponieważ żaden kod w moim przykładzie nie wymagał zapisania.Umieszczenie każdego z okien najwyższego poziomu w osobnej klasie zapewnia ponowne użycie kodu i lepszą organizację kodu. Wszelkie przyciski i odpowiednie metody, które są obecne w oknie, powinny być zdefiniowane w tej klasie. Oto przykład (zaczerpnięty stąd ):
Zobacz także:
Mam nadzieję, że to pomoże.
źródło
To nie jest zła konstrukcja; będzie działać dobrze. Jednak musisz mieć funkcje w funkcji, aby wykonywać polecenia, gdy ktoś kliknie przycisk lub coś
Więc to, co możesz zrobić, to napisać dla nich klasy, a następnie mieć w klasie metody, które obsługują polecenia dla kliknięć przycisku i tym podobne.
Oto przykład:
Zazwyczaj programy tk z wieloma oknami są wieloma dużymi klasami i we
__init__
wszystkich wpisach tworzone są etykiety itp., A następnie każda metoda obsługuje zdarzenia kliknięcia przyciskuNaprawdę nie ma właściwego sposobu, aby to zrobić, cokolwiek działa dla ciebie i wykonuje zadanie, o ile jest czytelne i możesz to łatwo wyjaśnić, ponieważ jeśli nie możesz łatwo wyjaśnić swojego programu, prawdopodobnie jest lepszy sposób, aby to zrobić .
Spójrz na Thinking in Tkinter .
źródło
OOP powinno być podejściem i
frame
powinno być zmienną klasy, a nie zmienną instancji .Źródła: http://www.python-course.eu/tkinter_buttons.php
źródło
TKinter
w Pythonie 2. Polecam używanietkinter
w Pythonie 3. Umieściłbym również ostatnie trzy linie kodu podmain()
funkcją i wywołałbym ją na końcu programu. Chciałbym zdecydowanie unikaćfrom module_name import *
, ponieważ zanieczyszcza globalnej przestrzeni nazw i może zmniejszyć czytelność.button1 = tk.Button(root, command=funA)
ibutton1 = ttk.Button(root, command=funA)
czytkinter
był on również importowany? Przy*
składni wyglądałyby tak oba wiersze kodubutton1 = Button(root, command=funA)
. Nie polecałbym używania tej składni.Organizowanie aplikacji przy użyciu klas ułatwia Tobie i innym współpracownikom łatwe debugowanie problemów i ulepszanie aplikacji.
Możesz łatwo zorganizować swoją aplikację w ten sposób:
źródło
Prawdopodobnie najlepszym sposobem nauczenia się struktury programu jest czytanie kodu innych osób, zwłaszcza jeśli jest to duży program, w którego tworzeniu uczestniczyło wiele osób. Po przyjrzeniu się kodowi wielu projektów powinieneś zorientować się, jaki powinien być styl konsensusu.
Python jako język wyróżnia się tym, że istnieją pewne silne wytyczne dotyczące formatowania kodu. Pierwszy to tak zwany „Zen Pythona”:
Na bardziej praktycznym poziomie jest PEP8 , przewodnik po stylu dla Pythona.
Mając to na uwadze, powiedziałbym, że twój styl kodu nie pasuje, szczególnie funkcje zagnieżdżone. Znajdź sposób na ich spłaszczenie, używając klas lub przenosząc je do oddzielnych modułów. Dzięki temu struktura programu będzie znacznie łatwiejsza do zrozumienia.
źródło
Osobiście nie stosuję podejścia zorientowanego obiektowo, głównie dlatego, że a) tylko przeszkadza; b) nigdy nie użyjesz tego ponownie jako modułu.
ale coś, co nie jest tutaj omawiane, to fakt, że musisz używać wątków lub przetwarzania wieloprocesowego. Zawsze. inaczej twoja aplikacja będzie okropna.
po prostu zrób prosty test: uruchom okno, a następnie pobierz jakiś adres URL lub cokolwiek innego. zmiany to twój interfejs użytkownika nie zostanie zaktualizowany, gdy trwa żądanie sieciowe. Oznacza to, że okno aplikacji zostanie zepsute. zależy od używanego systemu operacyjnego, ale w większości przypadków nie będzie przerysowywany, wszystko, co przeciągniesz przez okno, zostanie na nim otynkowane, dopóki proces nie powróci do głównej pętli TK.
źródło