# Canvas — Холст
Виджет Canvas() — Холст используется для добавления структурированной графики в приложение.
Синтаксис создания виджета подобен, другим объектам tkinter :
widget_name = Canvas(parent, options)
- parent — окно или фрейм (рамка), в котором будет размещаться холст;
- options — параметры настройки холста.
Базовые параметры
- bd — представляет ширину границы. Ширина по умолчанию — 2.
- bg — он представляет собой цвет фона холста.
- confine — он настроен на то, чтобы холст нельзя было прокручивать за пределами области прокрутки.
- cursor — курсор используется как стрелка, круг, точка и т.д. На холсте.
- height — представляет размер холста в вертикальном направлении.
- highlightcolor — представляет цвет выделения, когда виджет находится в фокусе.
- relief — представляет собой тип бордюра. Возможные значения: SUNKEN, RAISED, GROOVE и RIDGE.
- scrollregion — представляет координаты, заданные как кортеж, содержащий область холста.
- width Он представляет собой ширину холста.
- xscrollincrement — если задано положительное значение. Холст размещается только с кратным этому значению.
- xscrollcommand — если холст можно прокручивать, этот атрибут должен быть методом .set() горизонтальной полосы прокрутки.
- yscrollincrement — работает как xscrollincrement , но управляет вертикальным перемещением.
- yscrollcommand — если холст можно прокручивать, этот атрибут должен быть методом .set() вертикальной полосы прокрутки.
В tkinter от класса Canvas() создаются объекты-холсты, на которых можно «рисовать», размещая различные фигуры и объекты. Делается это с помощью вызовов соответствующих методов.
При создании экземпляра Canvas необходимо указать его ширину и высоту. При размещении геометрических примитивов и других объектов указываются их координаты на холсте. Точкой отсчета является верхний левый угол.
В программе ниже создается холст. На нем с помощью метода create_line() рисуются отрезки. Сначала указываются координаты начала (x1, y1), затем – конца (x2, y2):
from tkinter import * root = Tk() c = Canvas(root, width=200, height=200, bg='white') c.pack() c.create_line(10, 10, 190, 50) c.create_line(100, 180, 100, 60, fill='green', width=5, arrow=LAST, dash=(10,2), activefill='lightgreen', arrowshape="10 20 10") root.mainloop()
Остальные свойства являются необязательными. Так activefill определяет цвет отрезка при наведении на него курсора мыши.
Создание прямоугольников методом create_rectangle() :
… c.create_rectangle(10, 10, 190, 60) c.create_rectangle(60, 80, 140, 190, fill='yellow', outline='green', width=3, activedash=(5, 4)) …
Первые координаты – верхний левый угол, вторые – правый нижний. В приведенном примере, когда на второй прямоугольник попадает курсор мыши, его рамка становится пунктирной, что определяется свойством activedash .
Методом create_polygon() рисуется произвольный многоугольник путем задания координат каждой его точки:
… c.create_polygon(100, 10, 20, 90, 180, 90) c.create_polygon(40, 110, 160, 110, 190, 180, 10, 180, fill='orange', outline='black') …
Для удобства координаты точек можно заключать в скобки:
… c.create_polygon((40, 110), (160, 110), (190, 180), (10, 180), fill='orange', outline='black') …
Метод create_oval() создает эллипсы. При этом задаются координаты гипотетического прямоугольника, описывающего эллипс. Если нужно получить круг, то соответственно описываемый прямоугольник должен быть квадратом:
… c.create_oval(50, 10, 150, 110, width=2) c.create_oval(10, 120, 190, 190, fill='grey70', outline='white') …
Более сложные для понимания фигуры получаются при использовании метода create_arc() . В зависимости от значения опции style можно получить сектор (по умолчанию), сегмент (CHORD) или дугу (ARC). Также как в случае create_oval() координаты задают прямоугольник, в который вписана окружность (или эллипс), из которой «вырезают» сектор, сегмент или дугу. Опции start присваивается градус начала фигуры, extent определяет угол поворота:
… c.create_oval(10, 10, 190, 190, fill='lightgrey', outline='white') c.create_arc(10, 10, 190, 190, start=0, extent=45, fill='red') c.create_arc(10, 10, 190, 190, start=180, extent=25, fill='orange') c.create_arc(10, 10, 190, 190, start=240, extent=100, style=CHORD, fill='green') c.create_arc(10, 10, 190, 190, start=160, extent=-70, style=ARC, outline='darkblue', width=5) …
В данном примере светло-серый круг используется исключительно для наглядности.
На холсте можно разместить текст. Делается это с помощью метода create_text():
… c.create_text(100, 100, text="Hello World,\nPython\nand Tk", justify=CENTER, font="Verdana 14") c.create_text(200, 200, text="About this", anchor=SE, fill="grey") …
По умолчанию в заданной координате располагается центр текстовой надписи. Чтобы изменить это и, например, разместить по указанной координате левую границу текста, используется якорь со значением W (от англ. west – запад). Другие значения: N, NE, E, SE, S, SW, W, NW. Если букв, задающих сторону привязки, две, то вторая определяет вертикальную привязку (вверх или вниз «уйдет» текст от заданной координаты). Свойство justify определяет лишь выравнивание текста относительно себя самого.
# Упражнения
# Canvas. Идентификаторы, теги и анимация
Изучив размещение геометрических примитивов на экземпляре Canvas, в этом уроке рассмотрим, как можно обращаться к уже созданным фигурам для изменения их свойств, а также создадим анимацию.
В tkinter существует два способа «пометить» фигуры, размещенные на холсте, – это идентификаторы и теги. Первые всегда уникальны для каждого объекта. Два объекта не могут иметь одни и тот же идентификатор. Теги не уникальны. Группа объектов на холсте может иметь один и тот же тег. Это дает возможность менять свойства всей группы. Отдельно взятая фигура на Canvas может иметь как идентификатор, так и тег.
Методы, создающие фигуры на холсте, возвращают численные идентификаторы этих объектов, которые можно присвоить переменным, через которые позднее обращаться к созданным фигурам:
from tkinter import * root = Tk() c = Canvas(width=300, height=300, bg='white') c.focus_set() c.pack() ball = c.create_oval(140, 140, 160, 160, fill='green') c.bind('', lambda event: c.move(ball, 0, -2)) c.bind('', lambda event: c.move(ball, 0, 2)) c.bind('', lambda event: c.move(ball, -2, 0)) c.bind('', lambda event: c.move(ball, 2, 0)) root.mainloop()
В данном примере круг двигается по холсту с помощью стрелок на клавиатуре. Когда создавался круг, его идентификатор был присвоен переменной ball . Метод move() объекта Canvas принимает идентификатор и смещение по осям.
С помощью метода itemconfig() можно изменять другие свойства. Метод coords() устанавливает новые координаты фигуры, если они заданы. Если указывается только идентификатор или тег, то coords() возвращает текущие координаты:
from tkinter import * root = Tk() c = Canvas(width=200, height=200, bg='white') c.pack() rect = c.create_rectangle(80, 80, 120, 120, fill='lightgreen') def inFocus(event): c.itemconfig(rect, fill='green', width=2) c.coords(rect, 70, 70, 130, 130) c.bind('', inFocus) root.mainloop()
Здесь при получении холстом фокуса (нажать Tab) изменится цвет и размер квадрата.
В отличие от идентификаторов, которые являются уникальными для каждого объекта, один и тот же тег может присваиваться разным объектам. Дальнейшее обращение к такому тегу позволит изменить все объекты, в которых он был указан. В примере ниже эллипс и линия содержат один и тот же тег, а функция color изменяет цвет всех объектов с тегом group1. Обратите внимание, что в отличие от имени идентификатора (переменная), имя тега заключается в кавычки (строковое значение):
… oval = c.create_oval(30, 10, 130, 80, tag="group1") c.create_line(10, 100, 450, 100, tag="group1") def color(event): c.itemconfig('group1',fill="red",width=3) c.bind('', color) …
Метод tag_bind() позволяет привязать событие (например, щелчок кнопкой мыши) к определенной фигуре на Canvas. Таким образом, можно реализовать обращение к различным областям холста с помощью одного и того же события. Пример ниже иллюстрирует, как изменения на холсте зависят от того, где произведен клик:
from tkinter import * c = Canvas(width=460, height=100, bg='grey80') c.pack() oval = c.create_oval(30, 10, 130, 80, fill="orange") c.create_rectangle(180, 10, 280, 80, tag="rect", fill="lightgreen") trian = c.create_polygon(330, 80, 380, 10, 430, 80, fill='white',outline="black") def oval_func(event): c.delete(oval) c.create_text(80, 50, text="Круг") def rect_func(event): c.delete("rect") c.create_text(230, 50, text="Прямоугольник") def triangle(event): c.delete(trian) c.create_text(380, 50, text="Треугольник") c.tag_bind(oval, '', oval_func) c.tag_bind("rect", '', rect_func) c.tag_bind(trian, '', triangle) mainloop()
Метод delete() удаляет объект. Если нужно очистить холст, то вместо идентификаторов или тегов используется константа ALL.
# Упражнения
Практическая работа. Анимация в tkinter .
В данной программе создается анимация круга, который движется от левой границы холста до правой:
from tkinter import * root = Tk() c = Canvas(root, width=300, height=200, bg="white") c.pack() ball = c.create_oval(0, 100, 40, 140, fill='green') def motion(): c.move(ball, 1, 0) if c.coords(ball)[2] 300: root.after(20, motion) motion() root.mainloop()
Выражение c.coords(ball) возвращает список текущих координат объекта (в данном случае это ball). Третий элемент списка соответствует его второй координате x .
Метод after() вызывает функцию, переданную вторым аргументом, через количество миллисекунд, указанных первым аргументом.
Изучите приведенную программу и самостоятельно запрограммируйте постепенное движение фигуры в ту точку холста, где пользователь кликает левой кнопкой мыши. Координаты события хранятся в его атрибутах x и y ( event.x , event.y ).
Python tkinter canvas bind
С помощью метода tag_bind() можно привязать к определенному элементу в Canvas (например, к линии) событие:
tag_bind(тег_или_идентификатор_элемента, событие, функция)
Первый параметр представляет тег или идентификатор элеиментов, для которых добавляется событие.
Второй параметр — обрабатываемое событие.
Третий параметр — функция, которая выполняется при возникновении события
Рассмотрим небольшой пример:
from tkinter import * from tkinter import ttk root = Tk() root.title("METANIT.COM") root.geometry("250x200") canvas = Canvas(bg="white", width=250, height=150) canvas.pack(fill=BOTH, expand=1) # размеры прямоугольника big_size = (60, 60, 150, 150) small_size = (60, 60, 100, 100) # обработчики событий def make_big(event): canvas.coords(id, big_size) def make_small(event): canvas.coords(id, small_size) id = canvas.create_rectangle(small_size, fill="red") # привязка событий к элементу с идентификатором id canvas.tag_bind(id, "", make_big) canvas.tag_bind(id, "", make_small) root.mainloop()
Здесь на Canvas добавляется прямоугольник, идентификатор которого хранится в переменной id.
Сначала привязываем к прямоугольнику с идентификатором id событие «», то есть событие вхождения курсора в пределы прямогольника:
canvas.tag_bind(id, "", make_big)
Когда указатель мыши окажется в пределах прямогольника, сработает функция make_big, которая с помощью метода canvas.coords изменит координаты и размеры прямоугольника:
def make_big(event): canvas.coords(id, big_size)
Аналогичным образом привязывается событие «», которое срабатывает, когда указатель мыши выходит за пределы прямоугольника. В этом случае срабатывает функция make_small, которая уменьшит размер прямоугольника.