Canvas — это виджет библиотеки Tkinter, на котором программа на Python рисует 2D-графику: линии, фигуры, текст и изображения. Tkinter — стандартная кроссплатформенная библиотека графического интерфейса, она входит в поставку Python, ставить ее отдельно обычно не нужно.
Содержание
Разберем по шагам: как создать окно и холст, как устроена система координат, как рисовать примитивы, задавать цвета, делать простую анимацию и реагировать на мышь. Каждый пример — законченный и запускаемый на обычном рабочем столе.
Важно про запуск: примерам нужна графическая среда (экран, оконный менеджер). В headless-окружении без дисплея вызов Tk() завершится ошибкой вида no display name and no $DISPLAY environment variable — при этом сам код синтаксически корректен, запускать его надо в графической системе.
Минимальный рабочий пример
Начнем с целого работающего окна, а потом разберем строки.
import tkinter as tk
root = tk.Tk() # главное окно приложения
root.title("Графика на Canvas")
canvas = tk.Canvas(root, width=400, height=300, bg="white")
canvas.pack() # размещаем холст в окне
# круг задается рамкой (150, 100)-(250, 200), центр примерно в (200, 150)
canvas.create_oval(150, 100, 250, 200, fill="red", outline="black", width=2)
root.mainloop() # запускаем цикл обработки событий
Что произойдет: откроется окно 400×300 px с белым фоном, в центре — красный круг с черным контуром толщиной 2 px. Окно живет, пока работает mainloop(); закрыть его можно крестиком.
Разберем ключевые строки:
— tk.Tk() создает главное окно приложения.
— tk.Canvas(...) создает холст: width и height в пикселях, bg — цвет фона.
— canvas.pack() размещает холст в окне (о менеджерах размещения — ниже).
— create_oval(...) рисует эллипс или круг: fill — заливка, outline — контур.
— mainloop() запускает цикл событий; без него окно откроется и сразу закроется.
Разместить виджет в окне можно тремя менеджерами: pack() укладывает блоки друг за другом, grid() расставляет по сетке строк и столбцов, place() ставит по точным координатам. Для холста хватает pack(); смешивать pack и grid в одном контейнере нельзя.
Система координат холста
Начало координат (0, 0) находится в левом ВЕРХНЕМ углу холста. Ось X растет вправо, ось Y растет ВНИЗ — в отличие от школьной геометрии, где Y идет вверх. Для холста 400×300 точка (400, 300) — это правый нижний угол.
Все методы рисования принимают координаты в пикселях от этого угла. Прямоугольник и овал задаются рамкой из двух точек: левый верхний угол (x1, y1) и правый нижний (x2, y2). Держать эту рамку в голове важнее всего — большинство ошибок новичка именно в перепутанных углах.
Примитивы: линии, фигуры, текст
Один холст, на нем все базовые фигуры сразу.
import tkinter as tk
root = tk.Tk()
canvas = tk.Canvas(root, width=400, height=300, bg="white")
canvas.pack()
# 1. Отрезок (20,20)-(380,20); пунктир: штрих 4 px, пропуск 2 px
canvas.create_line(20, 20, 380, 20, fill="blue", width=2, dash=(4, 2))
# 2. Ломаная по трем точкам - лишние пары координат продолжают линию
canvas.create_line(20, 60, 200, 260, 380, 60, fill="green", width=2)
# 3. Прямоугольник по рамке: угол (40,90) и угол (160,180)
canvas.create_rectangle(40, 90, 160, 180, fill="#ffd54f", outline="black")
# 4. Овал, вписанный в рамку (220,90)-(360,180)
canvas.create_oval(220, 90, 360, 180, fill="orange", outline="red", width=2)
# 5. Многоугольник (треугольник) по трем вершинам, замыкается сам
canvas.create_polygon(200, 200, 160, 280, 240, 280, fill="purple")
# 6. Текст; по умолчанию точка (200,40) - его центр
canvas.create_text(200, 40, text="Canvas", font=("Arial", 16), fill="black")
root.mainloop()
Что нарисуется на белом холсте:
— сверху — синяя пунктирная горизонтальная линия;
— зеленая V-образная ломаная из трех точек;
— слева — желтый прямоугольник с черным контуром;
— справа — оранжевый овал с красным контуром;
— снизу по центру — фиолетовый треугольник;
— вверху по центру — надпись «Canvas».
Коротко про методы:
— create_line(x1, y1, x2, y2, ...) — отрезок; если передать больше пар координат, получится ломаная. Опция dash=(4, 2) дает пунктир: штрих 4 px, пропуск 2 px.
— create_rectangle(x1, y1, x2, y2, ...) — прямоугольник по рамке из двух углов.
— create_oval(x1, y1, x2, y2, ...) — эллипс, вписанный в рамку; если рамка квадратная, выйдет круг.
— create_polygon(...) — многоугольник по списку вершин, контур замыкается автоматически.
— create_text(x, y, text=...) — текст; по умолчанию точка (x, y) — его центр (сдвинуть привязку можно опцией anchor).
Дуга — это часть овала, для нее отдельный метод:
canvas.create_arc(50, 50, 250, 250, start=0, extent=120, fill="skyblue")
Здесь start — начальный угол в градусах (отсчет против часовой стрелки от направления «на 3 часа»), extent — на сколько градусов раскрыть дугу. Пример даст голубой сектор («кусок пирога») на 120 градусов.
Цвета
Цвет задается двумя способами — именем или HEX-кодом.
canvas.create_rectangle(10, 10, 90, 90, fill="tomato") # имя цвета
canvas.create_rectangle(110, 10, 190, 90, fill="#2196f3") # HEX #RRGGBB
Имена цветов — это набор предопределенных названий (red, white, tomato, skyblue и другие). Запись #RRGGBB задает интенсивность красного, зеленого и синего двумя шестнадцатеричными разрядами каждый: #2196f3 — оттенок синего. Заливку контролирует fill, цвет и толщину контура — outline и width.
Анимация: move и after
Анимация в Tkinter — это сдвиг фигуры маленькими шагами через равные промежутки времени. Работают два метода:
— canvas.move(item, dx, dy) сдвигает фигуру с идентификатором item на dx по X и dy по Y;
— root.after(ms, func) планирует однократный вызов функции func через ms миллисекунд.
Чтобы движение продолжалось, функция в конце снова планирует саму себя через after — получается цикл на событийной модели. Обычный while тут не подойдет: он заблокировал бы интерфейс, и окно перестало бы отвечать.
import tkinter as tk
root = tk.Tk()
canvas = tk.Canvas(root, width=400, height=200, bg="white")
canvas.pack()
ball = canvas.create_oval(0, 80, 40, 120, fill="red") # id фигуры
dx = 5
def move_ball():
global dx
x1, y1, x2, y2 = canvas.coords(ball) # текущая рамка фигуры
if x2 >= 400 or x1 <= 0: # у правой или левой стенки
dx = -dx # разворачиваем направление
canvas.move(ball, dx, 0) # сдвиг на dx по X
root.after(30, move_ball) # повторить через 30 мс
move_ball()
root.mainloop()
Что произойдет: красный шар едет вправо на 5 px за кадр, кадр раз в 30 мс (около 33 обновлений в секунду), а у правой и левой стенки меняет направление и отскакивает. Метод canvas.coords(item) возвращает текущие координаты рамки — по ним и проверяем столкновение.
Такой подход хорош для несложной анимации и мини-игр. Для крупных 2D-игр с множеством объектов и физикой удобнее Pygame — он для этого и создан.
Обработка событий мыши
Реакцию на мышь подключают методом bind: он связывает событие с функцией-обработчиком. Обработчик получает объект события, у которого есть поля x и y — координаты курсора внутри холста.
import tkinter as tk
root = tk.Tk()
canvas = tk.Canvas(root, width=400, height=300, bg="white")
canvas.pack()
def draw_dot(event):
r = 5
# event.x, event.y - точка клика внутри холста
canvas.create_oval(event.x - r, event.y - r,
event.x + r, event.y + r, fill="black")
canvas.bind("<Button-1>", draw_dot) # левая кнопка мыши
root.mainloop()
Что произойдет: каждый щелчок левой кнопкой ставит черную точку (круг радиусом 5 px) там, где был курсор. Частые обозначения событий: <Button-1> — левая кнопка, <Button-3> — правая, <B1-Motion> — движение с зажатой левой кнопкой (удобно для рисования от руки), <Motion> — просто перемещение курсора.
Выводы
- Canvas — виджет Tkinter для 2D-графики; Tkinter входит в стандартную поставку Python, обычно устанавливать его не нужно.
- Начало координат — в левом верхнем углу, ось Y направлена вниз; прямоугольник и овал задаются рамкой из двух противоположных углов.
- Примитивы рисуют методами create_line, create_rectangle, create_oval, create_polygon, create_text и create_arc; цвет задают именем или HEX-кодом.
- Анимация строится на паре move + after (событийный цикл), а реакция на мышь — на bind и координатах event.x / event.y.
- Для схем, визуализаций и мини-игр Canvas достаточно; для крупных 2D-игр с физикой берут Pygame.
Где применяется / связь с практикой
Canvas пригодится для несложных инструментов: диаграмм и графиков, схем, простых редакторов фигур, обучающих визуализаций, небольших игр. Это удобный способ закрепить основы Python — функции, переменные, работу с событиями — на видимом результате, а не на абстрактных задачах.
Освойте тему на практике
Если хотите освоить язык системно, от синтаксиса до прикладных задач, посмотрите курс Python Basic. Оценить формат и уровень занятий без оплаты можно на открытых уроках.
Смежные темы: 10 полезных библиотек для Python, Потоки (threads) в Python.
FAQ
Нужно ли устанавливать Tkinter отдельно? На большинстве сборок он идет вместе с Python. Проверить можно командой python -m tkinter — откроется тестовое окно. В некоторых дистрибутивах Linux модуль ставится отдельным пакетом (например, python3-tk в Debian и Ubuntu).
Можно ли сохранить рисунок с холста в PNG? Штатно Canvas экспортирует только в PostScript через canvas.postscript(...). Для PNG обычно рисуют то же самое параллельно в изображении с помощью библиотеки Pillow и сохраняют его.
Почему фигура не двигается, хотя я поменял ее координаты в переменных? Пересчет обычных переменных сам по себе ничего не перерисовывает. Двигать уже нарисованную фигуру нужно по ее идентификатору — методом canvas.move(item, dx, dy) или canvas.coords(item, ...).



