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()
2
3
4
5
6
7
8
9
10
11
12
13
14
Остальные свойства являются необязательными. Так 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))
…
2
3
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')
…
2
3
4
Для удобства координаты точек можно заключать в скобки:
…
c.create_polygon((40, 110), (160, 110), (190, 180), (10, 180), fill='orange', outline='black')
…
2
3
Метод create_oval()
создает эллипсы. При этом задаются координаты гипотетического прямоугольника, описывающего эллипс. Если нужно получить круг, то соответственно описываемый прямоугольник должен быть квадратом:
…
c.create_oval(50, 10, 150, 110, width=2)
c.create_oval(10, 120, 190, 190, fill='grey70', outline='white')
…
2
3
4
Более сложные для понимания фигуры получаются при использовании метода 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)
…
2
3
4
5
6
7
В данном примере светло-серый круг используется исключительно для наглядности.
На холсте можно разместить текст. Делается это с помощью метода 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")
…
2
3
4
По умолчанию в заданной координате располагается центр текстовой надписи. Чтобы изменить это и, например, разместить по указанной координате левую границу текста, используется якорь со значением 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('<Up>', lambda event: c.move(ball, 0, -2))
c.bind('<Down>', lambda event: c.move(ball, 0, 2))
c.bind('<Left>', lambda event: c.move(ball, -2, 0))
c.bind('<Right>', lambda event: c.move(ball, 2, 0))
root.mainloop()
2
3
4
5
6
7
8
9
10
11
12
13
В данном примере круг двигается по холсту с помощью стрелок на клавиатуре. Когда создавался круг, его идентификатор был присвоен переменной 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('<FocusIn>', inFocus)
root.mainloop()
2
3
4
5
6
7
8
9
10
11
12
13
Здесь при получении холстом фокуса (нажать 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('<Button-3>', color)
…
2
3
4
5
6
7
8
9
Метод 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, '<Button-1>', oval_func)
c.tag_bind("rect", '<Button-1>', rect_func)
c.tag_bind(trian, '<Button-1>', triangle)
mainloop()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
До кликов:
После кликов:
Метод 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()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Выражение c.coords(ball)
возвращает список текущих координат объекта (в данном случае это ball). Третий элемент списка соответствует его второй координате x
.
Метод after()
вызывает функцию, переданную вторым аргументом, через количество миллисекунд, указанных первым аргументом.
Изучите приведенную программу и самостоятельно запрограммируйте постепенное движение фигуры в ту точку холста, где пользователь кликает левой кнопкой мыши. Координаты события хранятся в его атрибутах x
и y
(event.x
, event.y
).