Глава 18 · Инструменты рисования
Карандаш: непрерывный штрих
Отдельные кружки создают разрывы. Соединяем каждую точку с предыдущей — и штрих становится одной линией.
Почему кружки на каждое движение — плохая идея
Раздел 18.7 рисовал свободный штрих кружками — по одному на каждое событие
<B1-Motion>. Работает, но у этого подхода есть три
проблемы:
- между кружками остаются разрывы, если мышь двигалась быстрее, чем приходили события;
- сама линия выглядит «бугристой», а не гладкой;
- кружок ничего не знает о том, где курсор был мгновение назад, — путь между двумя соседними событиями просто теряется.
Лучшая модель: помнить предыдущую точку
Вместо кружка на каждое событие — соединяем каждую новую точку с предыдущей отрезком прямой. Отрезков много, но вместе они образуют одну непрерывную линию:
karandash.py
def on_drag(self, event):
self.canvas.create_line(
self.state.last_x, self.state.last_y, event.x, event.y,
fill=self.state.color, width=self.state.width,
capstyle=tk.ROUND,
)
self.state.last_x, self.state.last_y = event.x, event.y
Отсюда код — это методы класса PaintApp
Начиная с этого раздела примеры пишутся как методы:
def on_drag(self, event), self.state, self.canvas. Все они принадлежат классу PaintApp, который мы соберём целиком в разделе 18.29 — до тех пор достаточно читать self.state.color как «текущий цвет приложения».
| Параметр | Зачем |
|---|---|
capstyle=tk.ROUND | скругляет концы каждого отрезка — стыки между ними не выглядят «зубчатыми» |
width | толщина штриха; чем она больше, тем заметнее была бы «зубчатость» стыков без capstyle |
А как же smooth=True? Здесь он не сработает
У
create_line() есть параметр smooth=True — Tk сглаживает ломаную, проводя через её точки кривую. Но сглаживать он умеет только внутренние точки одной линии, а каждый наш отрезок состоит ровно из ДВУХ точек — между ними нет ни одного угла. Добавить smooth=True в этот код можно, и Tk его молча примет, но на экране не изменится ровно ничего. Параметр стал бы полезен, если бы весь штрих был ОДНОЙ длинной ломаной — такой вариант описан ниже.Куда это можно развить: один штрих — одна ломаная
Сейчас каждое движение мыши создаёт отдельный элемент Canvas. Можно вместо этого создать линию один раз на
<Button-1> и на каждом движении дописывать к ней новую пару координат через coords() (раздел 18.18): тогда длинный штрих — это один элемент вместо сотни, а smooth=True наконец получает внутренние точки, которые действительно можно сгладить. В этой главе оставлен более простой вариант с отдельными отрезками — он короче и его легче отлаживать.Практика: непрерывный штрих карандаша
Модуль tkinter открывает нативное окно Python — выполните локально в VS Code, PyCharm или Jupyter
Практика выполняется локально