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

Końcowe okno Paint Pro z kilkoma narysowanymi figurami, paskiem narzędzi, paletą, suwakiem grubości i paskiem stanu
Właściwe okno w ostatecznej wersji to ten sam obraz, który otwierał rozdział w sekcji 18.1, ale teraz wiemy, z czego jest zrobiony.

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
Otwórz praktykę →

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.