Rozdział 18 · Canvas serio

Stan rysowania

Narzędzie, kolor, grubość i punkt rozpoczęcia gestu — to parametry, a nie same figury.

Co program powinien zapamiętać między wydarzeniami

Trzy zmienne z Sekcji 18.3 (tekuschaya_figura, tekuschij_cvet, tolschina) — uczciwy prototyp, ale wraz z rozwojem aplikacji dodaje się punkt wyjścia gestu, Ostatni punkt ołówka, id przybliżony wykres podglądu, oraz zmienne globalne pochodzą na zbyt wielu, by pamiętać o ich więzi.

DrawingStatetool: Toolcolor: strwidth: intstart_x: float | Nonestart_y: float | Nonelast_x: float | Nonelast_y: float | Nonepreview_id: int | None
Jeden obiekt zamiast ośmiu osobnych zmiennych — te same dane, ale z czytelną granicą.

Nowość: Enum — wcześniej znany lista wariantów

Podczas gdy narzędzie jest przechowywane na sznurku, żadnych słowo wydaje się akceptowalne: "pryamougolnik", "pryamougolnick", "квадрат". Python nie ma nic przeciwko — nie wie, jakie masz opcje Myślisz, że mają rację. Literówka pojawi się dużo później i w ogóle nie będzie obecna: znaczenie po prostu nie jest będzie się pokrywać z dowolną gałęzią ifi klikanie myszką cicho się zatrzymuje żeby coś narysować.

Ale narzędzie ma ograniczoną, wcześniej znaną liczbę opcji — ołówek, linia, prostokąt, elipsa, gumka. Dla takich przypadków w Python jest wyliczanie (Enum z modułu enum): ty raz zapisz wszystkie dopuszczalne wartości, a następnie używaj tylko ich.

enum_vpervye.py
from enum import Enum

class Tool(Enum):
    PENCIL = "pencil"
    LINE = "line"
    RECTANGLE = "rectangle"

print(Tool.RECTANGLE)          # Tool.RECTANGLE
print(Tool.RECTANGLE.value)    # rectangle
print(Tool.RECTANGLE is Tool.PENCIL)   # False
print(Tool.RECTANGL)           #AttributeError – literówka jest widoczna NATYCHMIAST

Trzy rzeczy, o których warto pamiętać Enum:

Główna różnica w stosunku do łańcucha: Tool.RECTANGL jest AttributeError przy pierwszym wywołaniu, a "pryamougolnick" — całkowicie „normalny” łańcuch znaków, o którym Python milczy.

Zbieramy DrawingState

Teraz połączmy oba narzędzia: Enum dla narzędzia i @dataclass (Rozdział 14.23) dla samego obiektu państwowego — Usuwa to odręczne __init__ i od razu daje zrozumiałe repr:

drawing_state.py
from dataclasses import dataclass
from enum import Enum

class Tool(Enum):
    PENCIL = "pencil"
    LINE = "line"
    RECTANGLE = "rectangle"
    OVAL = "oval"
    ERASER = "eraser"

@dataclass
class DrawingState:
    tool: Tool = Tool.PENCIL
    color: str = "#111827"
    width: int = 4
    start_x: float | None = None
    start_y: float | None = None
Enum zamiast kwestii – gdy warto
tekuschaya_figura = "pryamougolnik" działa, ale nie zauważy Python literówki w linii, dopóki kod nie zostanie wykonany i kształt nie zostanie cicho „nieznany” Tool.RECTANGLE jest takie samo pod względem znaczenia, ale literówka zostanie wykryta przez redaktora lub python -c "import module". Enum jest tu uzasadnione właśnie dlatego, że warianty instrumentu mają skończoną znaną liczbę. Jeśli istnieje tylko jeden wariant lub ich lista ciągle się zmienia, wystarczy regularna linia, a wyliczenie doda tylko ceremonię.
Prawdziwe okno: przycisk „Ołówek” na pasku narzędzi wygląda na wciśnięty (zanurzony), pozostałe — zwykłe
Prawdziwe okno: Ołówek jest wybrany — przycisk jest wizualnie „cofnięty”
Prawdziwe okno: Przycisk linii wygląda na naciśnięty (cofnięty), przycisk ołówka wraca do normalnego stanu
Prawdziwe okno: przełączono się na Linię — poprzedni przycisk wrócił do zwykłego widoku, nowy „zanurzony”.
Wybrane narzędzie jest widoczne, a nie tylko przechowywane w zmiennej
Stan — nie tylko to, co pamięta Python. Użytkownik powinien WIDZIEĆ, który narzędzie jest teraz wybrane, bez patrzenia w kod. W aplikacji końcowej set_tool() zmienia się jednocześnie self.state.tool I relief potrzebny przycisk — ta sama kombinacja «model → odzwierciedlenie na ekranie», co i render() w rozdziale 17.

Ścieżka tego rozdziału

od zmiennych globalnych do PaintApp
V1 — globalne (18.3)
3 oddzielne zmienne
proste, ale rosnące niekontrolowanie
V2 — DrawingState
@dataclass
parametry narzędzia w jednym miejscu
V3 — PaintApp (18.29)
DrawingState + dokument figur
pełna architektura aplikacji
Praktyka: Symulacja stanu rysowania
Automatyczne sprawdzanie – wybór narzędzi i parametrów bez Tkinter
Otwórz praktykę →