Canvas - Холст

Виджет Canvas() - Холст используется для добавления структурированной графики в приложение.

Синтаксис создания виджета подобен, другим объектам tkinter:

widget_name = Canvas(parent, options)
1
  • parent - окно или фрейм (рамка), в котором будет размещаться холст;
  • options - параметры настройки холста.

Базовые параметры

  1. bd - представляет ширину границы. Ширина по умолчанию - 2.
  2. bg - он представляет собой цвет фона холста.
  3. confine - он настроен на то, чтобы холст нельзя было прокручивать за пределами области прокрутки.
  4. cursor - курсор используется как стрелка, круг, точка и т.д. На холсте.
  5. height - представляет размер холста в вертикальном направлении.
  6. highlightcolor - представляет цвет выделения, когда виджет находится в фокусе.
  7. relief - представляет собой тип бордюра. Возможные значения: SUNKEN, RAISED, GROOVE и RIDGE.
  8. scrollregion - представляет координаты, заданные как кортеж, содержащий область холста.
  9. width Он представляет собой ширину холста.
  10. xscrollincrement - если задано положительное значение. Холст размещается только с кратным этому значению.
  11. xscrollcommand - если холст можно прокручивать, этот атрибут должен быть методом .set() горизонтальной полосы прокрутки.
  12. yscrollincrement - работает как xscrollincrement, но управляет вертикальным перемещением.
  13. yscrollcommand - если холст можно прокручивать, этот атрибут должен быть методом .set() вертикальной полосы прокрутки.

В tkinter от класса Canvas() создаются объекты-холсты, на которых можно «рисовать», размещая различные фигуры и объекты. Делается это с помощью вызовов соответствующих методов.

При создании экземпляра Canvas необходимо указать его ширину и высоту. При размещении геометрических примитивов и других объектов указываются их координаты на холсте. Точкой отсчета является верхний левый угол.

canvas_01

В программе ниже создается холст. На нем с помощью метода 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()
1
2
3
4
5
6
7
8
9
10
11
12
13
14

canvas_02

Остальные свойства являются необязательными. Так 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))
1
2
3
4

canvas_03

Первые координаты – верхний левый угол, вторые – правый нижний. В приведенном примере, когда на второй прямоугольник попадает курсор мыши, его рамка становится пунктирной, что определяется свойством 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')
1
2
3
4

canvas_04

Для удобства координаты точек можно заключать в скобки:

…
c.create_polygon((40, 110), (160, 110), (190, 180), (10, 180), fill='orange', outline='black')
1
2
3

Метод create_oval() создает эллипсы. При этом задаются координаты гипотетического прямоугольника, описывающего эллипс. Если нужно получить круг, то соответственно описываемый прямоугольник должен быть квадратом:

…
c.create_oval(50, 10, 150, 110, width=2)
c.create_oval(10, 120, 190, 190, fill='grey70', outline='white')
1
2
3
4

canvas_05

Более сложные для понимания фигуры получаются при использовании метода 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)
1
2
3
4
5
6
7

canvas_06

В данном примере светло-серый круг используется исключительно для наглядности.

На холсте можно разместить текст. Делается это с помощью метода 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")
1
2
3
4

canvas_07

По умолчанию в заданной координате располагается центр текстовой надписи. Чтобы изменить это и, например, разместить по указанной координате левую границу текста, используется якорь со значением W (от англ. west – запад). Другие значения: N, NE, E, SE, S, SW, W, NW. Если букв, задающих сторону привязки, две, то вторая определяет вертикальную привязку (вверх или вниз «уйдет» текст от заданной координаты). Свойство justify определяет лишь выравнивание текста относительно себя самого.

Упражнения

  1. Создайте на холсте подобное изображение:

canvas_08

  1. Для создания травы используется цикл.

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()
1
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()
1
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)
1
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()
1
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

До кликов:

canvas_11

После кликов:

canvas_12

Метод 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()
1
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).