Rozdział 18 · Ostatnie poprawki
Paint Pro — pełny program i wyniki rozdziału
Ten sam płótno co w rozdziale 18.7 — ale teraz z dokumentem, historią cofania i architekturą, która wytrzyma rozwój projektu.
Program końcowy
Plik jest kompletny, samodzielny i nie posiada niewidzialnych zależności od innych lekcji:
projects/tkinter/paint-app/paint_app.py
paint_app.py — struktura
class Tool(Enum): ...
@dataclass
class Shape: ...
@dataclass
class DrawingState: ...
def normalize_bounds(x1, y1, x2, y2): ...
class PaintApp:
def __init__(self, root): ...
def build_ui(self): ...
def set_tool(self, tool): ...
def set_color(self, hex_color): ...
def choose_custom_color(self): ...
def set_width(self, value): ...
def on_press(self, event): ...
def on_drag(self, event): ...
def on_release(self, event): ...
def render_document(self): ...
def undo(self): ...
def redo(self): ...
def clear_canvas(self): ...
def save_document(self): ...
def load_document(self): ...
def main():
root = tk.Tk()
app = PaintApp(root)
root.mainloop()
if __name__ == "__main__":
main()
Uruchom aplikację u siebie
python paint_app.py w terminalu — albo Run przycisku w VS Code, albo PyCharm. Porównaj z paint_app_basic.py (Rozdział 18.7) to to samo płótno i ta sama idea, ale z zupełnie inną architekturą wewnętrzną.Lista kontrolna gotowej aplikacji
MODEL
- dokument (
document) — lista figur, źródło prawdy - DrawingState są parametrami narzędzi, oddzielnymi od samych kształtów
- Canvas - Tylko wyświetlanie, przerysowane z dokumentu
NARZĘDZIA
- ołówek ciągłą kreską
- linia, prostokąt, owal z podglądem na żywo
- gumkę jako odrobinę koloru tła
- wybór narzędzia jest widoczny na ekranie, nie tylko w pamięci
HISTORIA
- undo/redo przez działania, a nie przez pojedyncze elementy Canvas
- nowe działanie oczyszcza redo_stack
- wyczyszczenie canvasa resetuje historię wraz z dokumentem
ZAPIS
- zapis i ładowanie rysunku przez JSON
- odwołania dialogów zapisu/otwarcia/wyboru koloru obsłużone szczerze
- łańcuch znaków stany i skróty klawiszowe
Most do rozdziału 19
Następnie: Przesuwaj się i powtarzaj zamiast czekać na kliknięcie
Rysowanka jest całkowicie zbudowana wokół oczekiwania na działania użytkownika — program reaguje, ale sam nie „żyje”. W następnym rozdziale — gra „Wąż” na Turtle — pojawi się własna pętla gry, w której program sam porusza obiektami klatka po klatce, niezależnie od tego, czy użytkownik w danym momencie coś klika.
Praktyka: Paint Pro w całości
Moduł tkinter otwiera natywne okno Python — wykonaj lokalnie w VS Code, PyCharm lub Jupyter
Praktyka kursuje lokalnie
Podsumowanie rozdziału 18
Co zbudowaliśmy i czego się nauczyliśmy
- Canvas przechowuje elementy (items), nie piksele—create_* dodaje do lista rekord, który sam widżet zapamiętuje i zwraca item_id.
- Współrzędne Canvas rosną w prawo i w dół od lewego górnego rogu — nie jak w Turtle, gdzie początek jest w centrum, a Y rośnie w górę.
- Rysowanie myszą — gest z trzech zdarzeń: press zapamiętuje początek, drag aktualizuje szkic, release utrwala wynik.
- Podgląd na żywo — to JEDEN element, który tworzy się raz i aktualizuje przez coords(), zamiast tworzyć ponownie przy każdym ruchu.
- Prostokąt i owal są określone przez dwa przeciwległe punkty; owal jest wpisany w powstały prostokąt, a nie określony przez środek i promień.
- Undo/redo działają według logicznych DZIAŁAŃ użytkownika, a nie według poszczególnych elementów Canvas — jeden pociągnięcie ołówkiem jest cofane w całości.
- Dokument (lista figur) — źródło prawdy; Canvas za każdym razem jest rysowany od nowa z niego przez render_document(), ta sama zasada, co render() w rozdziale 17.
- Zachowuje się nie obrazek, a dokument — jak JSON, który można wczytać i odbudować w dowolnym momencie.