Rozdział 18 · Historia i dokument

Cofnij działania (Undo)

Pojedynczy gest użytkownika może składać się z wielu elementów Canvas i musi być całkowicie anulowany.

Cofnij przez działanie, a nie przez Canvas przedmioty

Naiwną implementacją Undo jest po prostu usunięcie ostatniego elementu utworzonego Canvas. Problem: jeden kres ołówka składa się z WIELU pojedynczych segmentów (Rozdział 18.14) – „cofnij”

istoriya_deystviy.py
undo_stack = [
    [item_id_1, item_id_2, item_id_3],  # jeden pociągnięcie ołówka — trzy odcinki
    [item_id_4],                         # jeden prostokąt – jeden element
]

Ostateczna aplikacja rozwiązuje to poprzez dokument (sekcja 18.13, 18.29): każdy użytkownik Akcja — Jeden lub więcej obiektów Shape - W pełni dodane do Dokument można anulować w całości:

undo.py
def _commit_action(self, shapes):
    self.document.extend(shapes)
    self.undo_stack.append(shapes)   # JEDNA akcja — nawet jeśli shapes z wielu segmentów
    self.redo_stack.clear()
    self.render_document()

def undo(self):
    if not self.undo_stack:
        return
    shapes = self.undo_stack.pop()
    del self.document[len(self.document) - len(shapes):]
    self.redo_stack.append(shapes)
    self.render_document()
Prawdziwe okno: płótno z kilkoma figurami, w tym ostatnio narysowany prostokąt
Okno rzeczywiste: do Ctrl+Z — widoczny cały obraz, w tym ostatnia akcja.
Rzeczywiste okno: ten sam obszar roboczy bez ostatniego prostokąta, pozostałe kształty na miejscu
Realne okno: po Ctrl+Z – ostatnia AKCJA jest całkowicie usuwana, poprzednie wartości nie są ruszane.
render_document() jest tym samym render() co w rozdziale 17
Po anulowaniu dokument zmienia się, a płótno po prostu PRZERYSOWUJE się z niego na nowo — nie jest to punktowe usuwanie konkretnych elementów Canvas. Ten sam zasad „model zmienia akcje, Canvas tylko wyświetla aktualny stan” render() w grze „Kółko-krzyżyk”
Praktyka: Cofnij stos według akcji
Automatyczne skanowanie – undo usuwa WSZYSTKIE przedmioty z jednej akcji, zamiast tylko jednej
Otwórz praktykę →