Клавиатура и мышь
Используйте keyboard и mouse в обычном цикле: прочитайте ввод, измените переменные,
нарисуйте кадр и вызовите tick(). На первой итерации ввод нейтрален. Каждый tick()
готовит один снимок для следующей итерации; чтение не расходует и не изменяет его.
Непрерывное движение
Эта полная программа перемещает круг. Ось возвращает разность «положительная клавиша
нажата минус отрицательная нажата»: -1, 0 или 1. Если нажаты обе стороны или
ни одна, результат равен нулю.
from drawzero import *
x = y = 500
while True:
x += 4 * keyboard.axis('left', 'right')
y += 4 * keyboard.axis('up', 'down')
clear()
filled_circle(C.red, (x, y), 20)
tick()
Одно действие при нажатии; альтернативные клавиши и модификаторы
just_pressed истинен один кадр ввода, даже если клавишу успели отпустить в этом кадре.
Удержание и автоповтор не создают новых нажатий. just_released сообщает об отпускании.
Несколько частей программы могут прочитать один и тот же признак перехода.
Несколько аргументов означают хотя бы один: keyboard.pressed('left', 'a')
проверяет любой из двух вариантов управления. Для сочетания используйте
keyboard.pressed('ctrl') and keyboard.just_pressed('s').
Если отпустить Left, продолжая держать A, just_released('left', 'a') будет истинным.
Каждая сторона axis принимает одну клавишу или непустой плоский кортеж/список вариантов.
keyboard.axis(('left', 'a'), ('right', 'd')) возвращает целое число без сглаживания,
масштабирования по времени или приоритета последней клавиши. Повторы не усиливают ось.
shift, ctrl, alt, meta — виртуальные клавиши, объединяющие левую и правую стороны.
cmd означает meta. Группа нажимается с первой стороной и отпускается с последней.
Если левый Shift уже нажат, нажатие правого не создаёт нового нажатия группы;
отпускание левого при удержании правого не отпускает группу. Если за кадр отпустить
и снова нажать всю группу, истинны оба признака перехода. Доступны и отдельные
названия: lshift, rshift, lctrl, rmeta и другие.
Полный пример управления также перемещает фигуру в исходную точку щелчка:
from drawzero import *
x = y = 500
color = C.red
presses = 0
while True:
speed = 12 if keyboard.pressed('shift') else 4
dx = keyboard.axis(('left', 'a'), ('right', 'd'))
dy = keyboard.axis(('up', 'w'), ('down', 's'))
x += speed * dx
y += speed * dy
if keyboard.just_pressed('space'):
presses += 1
color = C.blue if color == C.red else C.red
for event in events():
if event.type == E.MOUSE_DOWN and event.button == M.LEFT:
x, y = event.pos
clear()
text(C.white, 'CONTROLS / STATE', (500, 70), 48)
text(C.white, 'Arrows or WASD move; Shift speeds up', (500, 150), 32)
text(C.white, 'Space changes color once; click places the square', (500, 205), 30)
text(C.cyan, f'Axis: ({dx}, {dy}) Shift: {keyboard.pressed("shift")}', (500, 300), 36)
text(C.yellow, f'Space presses: {presses}', (500, 360), 36)
filled_rect(color, (x, y), 35, 35)
filled_circle(C.yellow, mouse.pos, 6)
tick(fps=60)

Результат отрисовки примера при детерминированном воспроизведении, не проверка оборудования.
Координаты и кнопки мыши
mouse.pos — неизменяемая пара (x, y) в виртуальных координатах холста, включая
дробные значения и точки за его границами. Для изменяемой точки создайте Pt(*mouse.pos).
Проверяйте mouse.pressed('left'), mouse.just_pressed('right') или
mouse.just_released(M.MIDDLE). Регистр названий не важен; числа и константы равнозначны:
M.LEFT == 1, M.MIDDLE == 2, M.RIGHT == 3. Новый API поддерживает только эти три кнопки.
mouse.rel — сумма полученных смещений в виртуальных координатах, а не разность двух
положений. Повторное чтение её не сбрасывает. Координаты преобразуются при обработке
события: сохранённые события не меняются после изменения размера окна или виртуального
холста. Движения до и после изменения размера могут использовать разные масштабы.
При некорректном размере окна используется нейтральный масштаб.
Прокрутка и введённый текст
mouse.wheel возвращает (горизонталь, вертикаль) в единицах прокрутки, не пикселях.
Положительные направления — вправо и вверх (от пользователя). Флаг обратного направления
бэкенда учитывается один раз. Дробные точные значения, включая ноль, сохраняются;
если старый бэкенд их не предоставляет, используются целые значения. Размер холста
не влияет на прокрутку.
keyboard.typed объединяет подтверждённый текст в порядке поступления. Поддерживается
Unicode, включая кириллицу и греческие буквы. Незавершённая композиция доступна через
E.TEXT_EDITING и не попадает в typed. Поле unicode нажатия клавиши не добавляется
повторно: двойной вставки нет.
Упорядоченные события
Когда важен порядок, используйте events(). В течение кадра возвращается один и тот же
неизменяемый кортеж. keyboard.events содержит клавиши и текст, mouse.events — кнопки,
движение и прокрутку. Кортежи кешируются и ссылаются на те же объекты событий, что и общий
поток. Фокус и размер окна входят только в общий поток. Сохранённые кортежи остаются
действительными после следующих кадров. Поддерживаются перечисленные ниже семейства,
а не все события SDL. Закрытие окна, как обычно, завершает программу.
typed — удобная сводка, а не текстовый редактор. Последовательность текст → Backspace →
текст нужно обрабатывать по порядку. Эта полная программа также показывает прокрутку
по двум осям:
from drawzero import *
value = ''
scroll_x = scroll_y = 0
composition = ''
while True:
for event in events():
if event.type == E.TEXT_INPUT:
value += event.text
composition = ''
elif event.type == E.TEXT_EDITING:
composition = event.text
elif event.type == E.KEY_DOWN and event.key == K.BACKSPACE:
value = value[:-1]
elif event.type == E.FOCUS_LOST:
composition = ''
dx, dy = mouse.wheel
scroll_x += dx
scroll_y += dy
clear()
text(C.white, 'TEXT / TWO-DIMENSIONAL SCROLL', (500, 70), 40)
text(C.white, 'Type text; Backspace deletes; scroll moves the marker', (500, 150), 28)
text(C.cyan, value, (80, 300), 48, '<.')
text(C.gray, composition, (80, 370), 36, '<.')
text(C.yellow, f'Scroll: ({scroll_x:.1f}, {scroll_y:.1f})', (500, 480), 36)
line(C.gray, (200, 720), (800, 720))
line(C.gray, (500, 570), (500, 870))
filled_circle(C.orange, (500 + 30 * scroll_x, 720 - 30 * scroll_y), 22)
tick(fps=60)

Отрисованный результат воспроизведения событий текста и прокрутки, не проверка аппаратного ввода или IME. Пример удаляет один символ Python, а не целый графемный кластер Unicode.
Точное рисование и перетаскивание
event.pos, event.rel, event.buttons описывают момент события. mouse.pos и
mouse.pressed() — конечное состояние кадра. Кнопки проверяют через
M.LEFT in event.buttons. Умножать итоговое состояние кнопки на mouse.rel всего кадра
недостаточно для точного перетаскивания: часть движений могла произойти до нажатия
или после отпускания. Обрабатывайте события по порядку и отменяйте действие при потере фокуса:
from drawzero import *
segments = []
previous = None
while True:
for event in events():
if event.type == E.FOCUS_LOST:
previous = None
elif event.type == E.MOUSE_DOWN and event.button == M.LEFT:
previous = event.pos
elif event.type == E.MOUSE_MOVE:
if previous is not None and M.LEFT in event.buttons:
segments.append((previous, event.pos))
previous = event.pos
elif event.type == E.MOUSE_UP and event.button == M.LEFT:
if previous is not None and not event.source.cancelled:
segments.append((previous, event.pos))
previous = None
if keyboard.just_pressed('space'):
segments.clear()
clear()
text(C.white, 'PRECISE DRAWING', (500, 70), 48)
text(C.white, 'Hold left mouse button to draw; Space clears', (500, 150), 32)
for start, end in segments:
line(C.cyan, start, end, line_width=6)
filled_circle(C.yellow, mouse.pos, 8)
text(C.gray, f'Path segments: {len(segments)}', (500, 900), 32)
tick(fps=60)

Отрисовка фиксированной последовательности движений. Сохраняется каждое полученное движение; режима объединения движений нет.
Справочник API
| API | Результат |
|---|---|
keyboard.pressed(key, *other_keys) |
Хотя бы одна клавиша удерживается: bool |
keyboard.just_pressed(key, *other_keys) |
Хотя бы одно настоящее нажатие: bool |
keyboard.just_released(key, *other_keys) |
Хотя бы одно отпускание: bool |
keyboard.axis(negative, positive) |
Целое -1, 0 или 1 |
keyboard.typed |
Подтверждённый текст или '' |
keyboard.events |
Кортеж событий клавиш и текста |
mouse.pressed(button, *other_buttons) |
Хотя бы одна кнопка удерживается: bool |
mouse.just_pressed(button, *other_buttons) |
Хотя бы одно нажатие: bool |
mouse.just_released(button, *other_buttons) |
Хотя бы одно отпускание: bool |
mouse.pos, mouse.rel |
Неизменяемые пары виртуальных координат |
mouse.wheel |
Неизменяемая пара горизонтальной/вертикальной прокрутки |
mouse.events |
Кортеж событий мыши |
events() |
Кортеж всех поддерживаемых событий в порядке получения |
K, KEY |
Один объект с кодами клавиш: K.LEFT, K.a, K.A, K.SPACE |
M |
LEFT, MIDDLE, RIGHT |
MOD |
Типизированные флаги: SHIFT, CTRL, ALT, META/GUI, стороны L/R, NUM, CAPS, MODE, NONE |
E |
Константы типов событий из таблицы ниже |
tick(r=1, *, fps=30) |
Показывает рисунок, ждёт/опрашивает r раз, публикует один снимок; возвращает None |
Клавиши задают числовым кодом или названием из K без учёта регистра: left, a,
space и т. п. enter/return и esc/escape — явные синонимы. A и a обозначают
одну логическую клавишу и не подразумевают Shift. Это логические клавиши, а не физические
сканкоды или произвольный текст Unicode. Раскладка меняет соответствие физическим
клавишам; сканкоды сохранены для просмотра в событиях, но API физических привязок нет.
Запрос состояния требует хотя бы один аргумент и проверяет все аргументы, даже после
совпадения. Неизвестные имена/коды, логические значения, вложенные и пустые группы оси,
неподдерживаемые объекты вызывают ошибку. MOD — маски, не клавиши; используйте
event.mod & MOD.CTRL. Язык ошибок задаётся через set_lang('en') или set_lang('ru');
для похожих названий предлагается исправление.
Поля событий
Это неизменяемые кортежи со слотами, именованными типизированными полями и читаемым
представлением. Классы доступны в drawzero.utils.input. У всех есть type и source.
event.type |
Класс и поля |
|---|---|
E.KEY_DOWN, E.KEY_UP |
KeyEvent: key, mod, scancode, unicode, repeat (false для отпускания) |
E.TEXT_INPUT |
TextEvent: text |
E.TEXT_EDITING |
EditingEvent: text, start, length |
E.MOUSE_DOWN, E.MOUSE_UP |
ButtonEvent: button, pos, mod |
E.MOUSE_MOVE |
MotionEvent: pos, rel, buttons (frozenset идентификаторов), mod |
E.MOUSE_WHEEL |
WheelEvent: дробные x, y, историческое pos или None |
E.FOCUS_LOST, E.FOCUS_GAINED |
FocusEvent: без дополнительных полей |
E.WINDOW_RESIZED |
ResizeEvent: size — (ширина, высота) в нативных координатах окна |
Неизвестные поля клавиш: key=0, mod=MOD.NONE, scancode=None, unicode=''.
Автоповтор определяется флагом бэкенда или уже удерживаемой физической/логической
клавишей. Маски берутся из события или истории модификаторов, не из конечного состояния.
source — неизменяемый Provenance(window, which, touch, cancelled): неизвестные
идентификаторы и происхождение от касания равны None, cancelled по умолчанию false.
Явная отмена очищает соответствующее состояние без обычного признака отпускания.
Pygame не всегда помечает синтетические отпускания; DrawZero не пытается их угадать.
Аппаратные метки времени и точность сверх порядка полученной очереди не обещаются.
Кадры, фокус и время
Нажатие и отпускание за один кадр дают held=false, just-pressed=true, just-released=true. Несколько нажатий сохраняются в событиях, но признаки переходов остаются логическими. Пустой кадр очищает события, переходы, текст, движение и прокрутку, сохраняя удержание. Чтение не обращается к ОС, не опрашивает очередь, не ждёт и не создаёт окно.
tick(fps=60) и tick(fps=120) меняют ограничение частоты; tick(fps=0) отключает ожидание.
Отрицательные и неконечные значения запрещены. tick(60) по-прежнему означает 60 опросов.
sleep(t) ждёт/опрашивает int(t * 30 + 0.5) раз при 30 FPS и публикует накопленную
историю один раз. tick(0) и sleep(0) показывают рисунок и очищают временные данные
без опроса. Долгий sleep хранит O(число полученных событий) истории. Очередь SDL конечна:
если надолго блокировать программу, ввод может потеряться до получения DrawZero.
Потеря фокуса очищает удерживаемые клавиши/кнопки и накопленное движение без вымышленных
отпусканий. Настоящие более ранние переходы сохраняются; отменяйте перетаскивание и
композицию при E.FOCUS_LOST. Выход мыши из окна сам по себе не означает потерю фокуса.
После пакета с возвращением фокуса DrawZero сверяет конечное удержание с состоянием
pygame без новых нажатий и без удаления настоящей истории переходов. Снимок содержит
только логические клавиши; физические соответствия восстанавливаются при следующих нажатиях.
В EJUDGE ввод нейтрален и сам по себе не импортирует графический бэкенд. quit()
окончательно закрывает окно в этом процессе; последующее рисование не создаёт его заново.
Статический рисунок, как и раньше, остаётся открытым до закрытия пользователем.