Внешние модули в Python

Внутренний функционал питона довольно мощный, и его вполне достаточно для реализации многих проектов. Однако питон не был бы таким популярным среди программистов, если бы не мог расширять свой функционал за счет дополнительных модулей (ещё их называют библиотеками или пакетами) с помощью всего лишь одной строчки кода.

Каждый существующий модуль написан для решения задач в конкретной области. И первым модулем, который не включён в стандартную библиотеку питона, с которым мы познакомимся, будет модуль drawzero.

drawzero — это простая и удобная графическая библиотека, в которой есть функции для рисования простых фигур. Чтобы получить к ним доступ, надо в начале программы написать строку

from drawzero import *

Установка drawzero

Перед первым использованием модуль drawzero нужно установить. Для этого в терминале нужно выполнить команду

pip install drawzero --upgrade --user

Под linux и MacOS вместо pip нужно вводить pip3.

Если слово «терминал» непонятно, то можно запустить вот такую программу:

import os, sys python = sys.executable user = '--user' if 'venv' not in python else '' cmd = '"{}" -m pip install drawzero --upgrade {}'.format(python, user) print(cmd) os.system(cmd)

Если в результате её запуска вывод будет примерно такой как ниже, то у вас успех!

C:\some\path\Python38\python.exe -m pip install drawzero --upgrade --user
Collecting drawzero
  ... что-то про downloading или Using cached
Collecting pygame
  ... что-то про downloading или Using cached
Installing collected packages: pygame, drawzero
Successfully installed drawzero-0.1.4 pygame-1.9.6

A. Основы основ

Итак, приступим к рисованию!

Скопируйте и запустите программу ниже. В результате запуска должно открыться окно с нарисованной по диагонали красной линией. Сдавать код этой задачи не нужно :)

from drawzero import * line('red', (0, 0), (1000, 1000))

Осваиваем геометрию с помощью кода

Система координат в программировании и система координат в математике немного отличаются. В программировании точка с координатами (0, 0) находится в верхнем левом углу. Ось x направлена от неё вправо, а ось y — вниз.

Любая точка имеет позицию (координату) относительно оси x и относительно оси y, поэтому координаты каждой точки это пара чисел — сначала x, потом y. Эти координаты указываются через запятую и записываются в круглых скобках.

Рисование отрезка выполняется, как мы уже знаем, с помощью команды line. В скобках указываются параметры: цвет и две точки — концы отрезка. Именно в таком порядке.

Цвет пока можно выбирать из следующих вариантов: "black", "white", "red", "green", "blue", "yellow", "brown". Скоро мы научимся выбирать любые цвета.

Например:

line('red', (300, 200), (700, 400))
# 'red' — цвет линии,
# (300, 200) — один конец отрезка,
# (700, 400) — второй конец отрезка

save_to_var

Новость: строчки кода, начинающиеся с символа "#" называются в Python комментариями. Эти строчки предназначены для пояснения частей кода, чтобы в нём было проще разобраться. Особенно когда этот код читает не тот, кто его писал. Всё, что написано в такой строке, не считается программой и не выполняется.

Закомментировать сразу несколько строк кода можно, предварительно выделив эти строки, нажать Ctrl-/ (нажав и удерживая клавишу Ctrl, нажать клавишу /). Повторное нажатие той же комбинации клавиш убирает комментарии в блоке кода, если он был перед этим закомментирован.

Рисование окружности выполняется с помощью команды circle. В скобках указываются параметры: цвет, координаты центра окружности и радиус:

circle('yellow', (500, 300), 200)
# 'yellow' — цвет окружности,
# (500, 300) — координаты центра окружности,
# 200 — радиус

save_to_var

Рисование прямоугольника выполняется с помощью команды rect. В скобках указываются параметры: цвет, координаты левой верхней вершины, ширина (вдоль оси x), высота (вдоль оси y). То есть, при помощи такой функции можно рисовать только прямоугольники, параллельные осям координат.

rect('blue', (300, 200), 400, 200)
# 'blue' — цвет,
# (300, 200) — координаты верхнего левого угла,
# 400 —  ширина,
# 200 — высота

save_to_var

B. Три линии

Нарисуйте три линии так, чтобы получился треугольник (любой).

save_to_var

C. Три окружности

Теперь нарисуйте три окружности. Все три центра должны быть разными точками, а окружности вложены друг в друга и не пересекаться. То есть вторая окружность должна быть строго внутри первой, а третья — внутри второй.

Примерно вот так:

save_to_var

D. Два прямоугольника

Нарисуйте прямоугольник внутри другого прямоугольника так, чтобы между ними получилась ровная "рамка".

save_to_var

Создание более сложных фигур

Рисуя треугольник линиями, можно заметить, что каждую точку мы выписывали дважды, потому что она была концом двух отрезков. Может быть можно сделать то же самое экономнее?

Нам поможет функция рисования многоугольника polygon. Первый параметр это уже знакомый нам цвет, после которого надо перечислить координаты вершин многоугольника.

polygon('blue', (300, 200), (700, 300), (500, 400))
# 'blue' — цвет,
# (300, 200) — первая точка многоугольника,
# (700, 300) — вторая точка многоугольника,
# (500, 400) — третья точка многоугольника

Если в многоугольнике больше трёх вершин, нужно учесть, что перечислять вершины в произвольном порядке нельзя. Представьте, что вы обходите эту фигуру по часовой стрелке или против часовой стрелки. В функции polygon надо перечислять вершины одним из этих способов, начиная с любой вершины. Если порядок вершин неверный, то может получиться, например, что-то такое:

save_to_var

Пока мы рисовали только контуры. Теперь научимся рисовать закрашенные фигуры. Это может быть круг, прямоугольник и многоугольник. Для получения закрашенной фигуры есть команды: filled_circle, filled_rect, filled_polygon с такими же параметрами, как и у неокрашенных фигур.

from drawzero import *
filled_circle("red", (550, 450), 50)
filled_rect("green", (700, 200), 200, 200)
filled_polygon("blue", (100, 100), (400, 200), (300, 300))

save_to_var

E. Три треугольника

Нарисуйте три треугольника так, чтобы два из них не пересекались и находились внутри третьего.

Примерно вот так:

save_to_var

F. Фоторамка

Теперь нарисуйте прямоугольную рамку зелёного цвета ('green'). Размер "внешней" части 700x400. Ширина рамки 100. Внутренность рамки должна быть чёрной ('black'). Постарайтесь обойтись всего двумя командами из библиотеки drawzero.

save_to_var

Использование переменных

Мы познакомились с основными возможностями библиотеки drawzero. Теперь пора вспомнить про переменные — они нам скоро пригодятся.

Попробуем нарисовать какую-нибудь простенькую фигуру, например прямоугольник с закруглёнными концами.

from drawzero import *
filled_rect('yellow', (300, 500), 500, 100)
filled_circle('yellow', (300, 550), 50)
filled_circle('yellow', (800, 550), 50)

Координаты центра окружности это середины левой и правой (вертикальных) сторон прямоугольника и их можно посчитать. Это и правда несложно. Но что, если эту картинку надо перерисовать в другом месте или, скажем, сделать исходный прямоугольник чуть выше или шире? Это по-прежнему будет несложно сделать, но придётся пересчитывать координаты центров окружностей. А если картинка такая?

from drawzero import *
filled_rect('yellow', (300, 500), 500, 150)
filled_circle('yellow', (300, 575), 75)
filled_circle('yellow', (800, 575), 75)
filled_rect('yellow', (475, 325), 150, 500)
filled_circle('yellow', (550, 325), 75)
filled_circle('yellow', (550, 825), 75)

Всего-то — сделали полоски чуть шире. Пришлось пересчитать почти все координаты. Теперь представим себе, что это всё надо будет пересчитать несколько раз.

Напишем ту же программу по шагам, но для вычисления координат станем использовать переменные. Что нам нужно знать об этой фигуре, для того, чтобы её нарисовать? Нам надо знать где она находится и её главные размеры.

save_to_var

Место можно задать по-разному. Мы запомним координаты левого верхнего угла. Размеры фигуры определяются размерами прямоугольника. А радиус круга это половина его высоты, поэтому размеров прямоугольника достаточно. Не поленимся ввести для радиуса отдельную переменную, код так будет лучше читаться.

left = 300
top = 500
w = 500
h = 150
r = h // 2

Итак, всё готово для рисования. Теперь пишем те же самые вызовы функций рисования прямоугольников и кругов, но для вычисления всех координат используем только переменные. Надо только придумать — как вычислить координаты вертикального прямоугольника, используя имеющиеся переменные?

save_to_var

Очень полезно нарисовать картинку на бумаге и разобраться, откуда берутся формулы в программе, представленной ниже.

from drawzero import *
# left, top — координаты левого верхнего угла прямоугольника
left = 300
top = 500
# w, h — ширина и высота прямоугольника; r — радиус окружности
w = 500
h = 150
r = h // 2
filled_rect('yellow', (left, top), w, h)
filled_circle('yellow', (left, top + r), r)
filled_circle('yellow', (left + w, top + r), r)
filled_rect('yellow', (left + w // 2 - r, top - w // 2 + r), h, w)
filled_circle('yellow', (left + w // 2, top - w // 2 + r), r)
filled_circle('yellow', (left + w // 2, top + w // 2 + r), r)

В нашей программе стало в 2 раза больше строк, зато перерисовать эту фигуру в другом месте или поменять её размер стало проще простого. Надо только изменить нужные переменные. И всё! Все координаты и размеры пересчитаются автоматически.

G. Два пластыря

В аптечке есть два пластыря в форме креста со скруглёнными краями. В коде ниже есть пример одного из них, размер второго (ширина) равен 300. Подберите место, куда надо «наклеить» эти два пластыря, чтобы закрыть все порезы, которые отмечены красными треугольниками.

Используйте для перемещения переменные, объявленные в коде. Пропорции должны быть сохранены (меньшая сторона в 5 раз меньше большей).

cross

from drawzero import * # это порезы, их не нужно трогать filled_polygon('red', (260, 340), (310, 310), (320, 390)) filled_polygon('red', (510, 295), (620, 305), (590, 405)) filled_polygon('red', (720, 600), (655, 700), (722, 730)) filled_polygon('red', (550, 550), (510, 350), (570, 430)) filled_polygon('red', (510, 70), (517, 134), (580, 200)) filled_polygon('red', (630, 340), (730, 360), (630, 390)) filled_polygon('red', (690, 820), (710, 760), (680, 780)) filled_polygon('red', (750, 690), (830, 710), (730, 720)) filled_polygon('red', (520, 620), (590, 610), (550, 640)) # left, top — координаты левого верхнего угла прямоугольника # w, h — большая и меньшая стороны прямоугольника r — радиус окружности # параметры ниже нужно подобрать left = 220 top = 650 w = 500 h = w // 5 r = h // 2 filled_rect('yellow', (left, top), w, h) filled_circle('yellow', (left, top + r), r) filled_circle('yellow', (left + w, top + r), r) filled_rect('yellow', (left + w // 2 - r, top - w // 2 + r), h, w) filled_circle('yellow', (left + w // 2, top - w // 2 + r), r) filled_circle('yellow', (left + w // 2, top + w // 2 + r), r)

H. Скруглим углы

Давайте теперь сделаем не такие острые углы. Нарисуйте такую картинку:

save_to_var

Только "скруглить" угол можно по-разному. В идеальной фоторамке ширина должна быть одинаковой и в углах тоже. Но как понять, что такое "ширина рамки в углу"?

Давайте так: ширина это расстояние от точки на внешней границы к ближайшей к ней точке на внутренней. Изучите картинку со схемой и вы поймёте, что надо нарисовать (и в какой последовательности).

А ещё хорошо бы сделать всё на белом фоне! Для того, чтобы залить весь экран одним цветом, используйте команду `fill`. Например, заливка красным выглядит так:

fill('red')

save_to_var

I. Мишень

Хм, простая картинка — колечки одинаковой ширины. Ясно, что рисовать чёрные 'black' и белые 'white' круги, но в какой последовательности? Справитесь?
Тут, кстати, и циклы могут пригодиться :)

Все числовые данные в этой и следующих программах "спрячьте" в переменные, которые должны быть определены в начале программы. Постарайтесь дать переменным такие названия, чтобы по ним можно было определить, что именно обозначает данная переменная. Используйте английские слова или их сокращения.

save_to_var

J. Забор

Хорошо, мишень нарисовали, а куда её повесить? Может на забор?

Все числовые данные в этой и следующих программах "спрячьте" в переменные, которые должны быть определены в начале программы. Постарайтесь дать переменным такие названия, чтобы по ним можно было определить, что именно обозначает данная переменная. Используйте английские слова или их сокращения.

save_to_var

JA. Клеточки

Разбейте всё окно на одинаковые прямоугольные клетки. Программа считывает два числа: $N1$ - число вертикальных линий и $N2$ - число горизонтальных линний. Размер окна - $1000 \times 1000$ (его тоже нужно запомнить в переменной). Лишние линии рисовать не надо.

Картинка для $N1 = 10, N2 = 7$ должна выглядеть так:

bars

А если нацело не делится?

Если для вычисления расстояния между линиями мы будем использовать целочисленное деление, то может оказаться ненулевой остаток, и линии будут распределены неравномерно. Если же расстояние между линиями будет дробным числом, то линии распределятся равномерно. При рисовании координаты концов будут округляться до целого числа пикселей, но от расчётного значения будут отличаться не более, чем на полпикселя.

JB. Парабола

bars

Картинка нарисована с помощью отрезков, их огибающие - фрагменты парабол. Программа получает на вход число $N$ - количество отрезков с одной стороны картинки (вторая - симметричная). Расстояния между концами отрезков по одной стороне одинаковы. На картинке для $N = 5$ видно, как нужно рисовать отрезки.
Размер окна - $1000 \times 1000$.

bars

JC. Наклонные клеточки

Расчертите окно наклонными квадратиками. Программа получает на вход число $D$ - диагональ квадратика. Если рисовать отрезки, концы которых находятся за пределами окна, то тоже получится такая картинка. Но в этой задаче требуется, чтобы концы всех отрезков были ровно на границе окна.
Размер окна - $1000 \times 1000$.

bars

JD. Прямоугольники

Программа получает на вход три числа: $X < 500$, $Y < 500$ - координаты верхнего левого угла самого большого прямоугольника, $D$ - расстояние между прямоугольниками.
Размер окна - $1000 \times 1000$.

bars

Работа с цветами

Пора научиться создавать свои цвета. Каждый цвет состоит из трёх компонентов: красного, зелёного и синего. Наверняка вам встречалась аббревиатура RGB (сокращение от Red, Green и Blue).

Представьте, что в абсолютно тёмной комнате вы светите на стену тремя фонариками: красным, зелёным и синим. У каждого есть регулировка интенсивности — число от 0 (фонарик выключен) до 255 (фонарик светит максимально ярко). Все фонарики светят в одну и ту же точку стены и в зависимости от настроек интенсивности всех трёх фонариков на стене получается пятно определённого цвета. Вот несколько примеров:

В библиотеке drawzero можно определить свой цвет при помощи тройки чисел, взятой в скобки. Эту тройку можно запомнить в переменной и использовать при вызове всех функций рисования из модуля drawzero.

Цвета, приведённые в примере выше можно было сохранить так:

black = (0, 0, 0)
white = (255, 255, 255)
red = (255, 0, 0)
violet = (255, 0, 255)

Нарисуем картинку из предыдущего параграфа, определив свои цвета:

from drawzero import *
light_blue = (73, 151, 231)
sand_yellow = (244, 215, 111)
coral_red = (245, 129, 129)
filled_circle(coral_red, (150, 150), 10)
filled_rect(sand_yellow, (200, 100, 50, 50))
filled_polygon(light_blue, (90, 100), (70, 120), (30, 80))

save_to_var

K. Радуга

Задайте свои цвета с помощью переменных и нарисуйте радугу.

rainbow

L. Даже так можно?

Нарисуйте такую фигуру:

save_to_var

Надо обойтись 5 вызовами функций из модуля drawzero.

LA. Шахматная доска

Программа получает на вход три числа: N - число клеток (по горизонтали и по вертикали одинаковое), SIZE - размер одной клетки, MARGIN - ширина внешней рамки. Цвета выберите на свой вкус.
Каждый квадратик - отдельный прямоугольник. Внутри цикла должен быть ровно один вызов функции из библиотеки drawzerow.

rainbow

LB. Цветные прямоугольники

Программа получает на вход три числа: $X < 500$, $Y < 500$ - координаты верхнего левого угла самого большого прямоугольника, $N$ - число прямоугольников. Цвета равномерно меняются от синего (0, 0, 255) до голубого (0, 255, 255).
Размер окна - $1000 \times 1000$.

На первой картинке $X = 100, Y = 200, N = 5$, на второй $X = 250, Y = 50, N = 25$.

rect rect

Как сделать так, чтобы цвета менялись равномерно?

Надо найти, на какую величину должна меняться яркость зелёного цвета на каждом шаге, и добавлять её к яркости текущего цвета. Вычисленная так яркость будет действительным числом, поэтому при указании цвета её необходимо округлять с помощью функции round (эта функция с одним параметром даёт в ответе целое число).

Что-то всё равно не получается...

При вычислении длины интервала надо не забывать, что число интервалов не равно числу их граничных точек (в данном случае числу разных раскрашенных прямоугольников).

LC. Цветная лесенка - 1

Программа получает на вход три числа: $W, H$ - ширина и высота лестницы, $N$ - число ступенек. Цвета равномерно меняются от лилового (255, 0, 255) до синего (0, 0, 255).
Размер окна - $1000 \times 1000$.

На первой картинке $W = 700, H = 600, N = 5$, на второй $W = 900, H = 800, N = 25$.

ladder ladder

Как сделать так, чтобы цвета менялись равномерно?

Надо найти, на какую величину должна меняться яркость красного цвета на каждом шаге, и вычитать её из яркости текущего цвета. Вычисленная так яркость будет действительным числом, поэтому при указании цвета её необходимо округлять с помощью функции round (эта функция с одним параметром даёт в ответе целое число).

Что-то всё равно не получается...

При вычислении длины интервала надо не забывать, что число интервалов не равно числу их граничных точек (в данном случае числу разных раскрашенных прямоугольников).

LD. Цветная лесенка - 2

Программа получает на вход два числа: $N$ - число ступенек, $W$ - ширина одной ступеньки. Цвета равномерно меняются от красного (255, 0, 0) до жёлтого (255, 255, 0), потом до зелёного (0, 255, 0).
Размер окна - $1000 \times 1000$.

На первой картинке $N = 5, W = 200$, на второй $N = 15, W = 100$.

ladder-5-200 ladder-15-100