python 3 как отследить нажатие на кнопки
Отследить нажатие кнопок можно через модуль keyboard :
pip install keyboard
- Это пример для отслеживания клика по горячим кнопкам:
import keyboard def foo(): print('World') keyboard.add_hotkey('Ctrl + 1', lambda: print('Hello')) keyboard.add_hotkey('Ctrl + 2', foo) keyboard.wait('Ctrl + Q')
import keyboard def print_pressed_keys(e): print(e, e.event_type, e.name) keyboard.hook(print_pressed_keys) keyboard.wait()
Отслеживать
ответ дан 12 июн 2018 в 11:30
77k 6 6 золотых знаков 56 56 серебряных знаков 123 123 бронзовых знака
Вот таким способом решил эту задачу я:
import keyboard translate = < 'down':' нажал на клавишу ', 'up':' отпустил клавишу ' >def print_pressed_keys(e): print( 'Пользователь <><>'.format(translate[e.event_type], e.name) ) keyboard.hook(print_pressed_keys) keyboard.wait()
Как видишь, я использовал модуль keyboard.
Подробнее ознакомиться с ним можно здесь
Отслеживать
ответ дан 12 июн 2020 в 20:05
101 9 9 бронзовых знаков
pip install pynput
Вот таким способом:
from pynput.keyboard import Key, Listener def on_press(key): print(' pressed'.format(key)) def on_release(key): print(' release'.format(key)) if key == Key.esc: # Stop listener return False # Collect events until released with Listener(on_press=on_press, on_release=on_release) as listener: listener.join()
Python | PyAutoGUI | Как сделать активацию по нажатии клавиши?
Как сделать активацию по нажатии клавиши в библиотеке PyAtuoGui
(Если нельзя)
То благодаря какой(му) библиотеке/коду можно?
(Библиотеки: Tkinter , Kivy — отпадают)
(Код:
key = input(‘Клавиша: ‘)
if key == a:
print(‘Нажата клавиша’ + a)
Так же отпадает, так как мне нужна активация в афк режиме (То есть не в программу вводить а просто на клавиатуре нажать)
- Вопрос задан более трёх лет назад
- 12645 просмотров
4 комментария
Средний 4 комментария
Meakin @Meakin Автор вопроса
Не думаю что я задал ультра-сверх сложный вопрос, почему 24 человека не могут мне помочь?
UPD: 48 Человек
События клавиатуры
Человек может управлять объектами в игре в основном с помощь клавиатуры, мыши, джойстика. Когда на «манипуляторах» что-то двигается или нажимается, то возникают события определенных типов. Обработкой событий занимается модуль pygame.event , который включает ряд функций, наиболее важная из которых уже ранее рассмотренная pygame.event.get() , которая забирает из очереди произошедшие события.
В pygame, когда фиксируется то или иное событие, создается соответствующий ему объект от класса Event . Уже с этими объектами работает программа. Экземпляры данного класса имеют только свойства, у них нет методов. У всех экземпляров есть свойство type . Набор остальных свойств события зависит от значения type .
События клавиатуры могут быть двух типов (иметь одно из двух значений type ) – клавиша была нажата, клавиша была отпущена. Если вы нажали клавишу и отпустили, то в очередь событий будут записаны оба. Какое из них обрабатывать, зависит от контекста игры. Если вы зажали клавишу и не отпускаете ее, то в очередь записывается только один вариант – клавиша нажата.
Событию типа «клавиша нажата» в поле type записывается числовое значение, совпадающее со значением константы pygame.KEYDOWN . Событию типа «клавиша отпущена» в поле type записывается значение, совпадающее со значением константы pygame.KEYUP .
У обоих типов событий клавиатуры есть атрибуты key и mod . В key записывается конкретная клавиша, которая была нажата или отжата. В mod – клавиши-модификаторы ( Shift , Ctrl и др.), которые были зажаты в момент нажатия или отжатия обычной клавиши. У событий KEYDOWN также есть поле unicode , куда записывается символ нажатой клавиши (тип данных str ).
Рассмотрим, как это работает. Пусть в центре окна имеется круг, который можно двигать по горизонтали клавишами стрелок клавиатуры:
import pygame import sys FPS = 60 W = 700 # ширина экрана H = 300 # высота экрана WHITE = (255, 255, 255) BLUE = (0, 70, 225) sc = pygame.display.set_mode((W, H)) clock = pygame.time.Clock() # координаты и радиус круга x = W // 2 y = H // 2 r = 50 while 1: for i in pygame.event.get(): if i.type == pygame.QUIT: sys.exit() elif i.type == pygame.KEYDOWN: if i.key == pygame.K_LEFT: x -= 3 elif i.key == pygame.K_RIGHT: x += 3 sc.fill(WHITE) pygame.draw.circle(sc, BLUE, (x, y), r) pygame.display.update() clock.tick(FPS)
В цикле обработки событий теперь проверяется не только событие выхода, но также нажатие клавиш. Сначала необходимо проверить тип, потому что не у всех событий есть атрибут key . Если сразу начать проверять key , то сгенерируется ошибка по той причине, что могло произойти множество событий. Например, движение мыши, у которого нет поля key . Соответственно, попытка взять значение из несуществующего поля ( i.key ) приведет к генерации исключения.
Часто проверку и типа и клавиши записывают в одно логическое выражение ( i.type == pygame.KEYDOWN and i.key == pygame.K_LEFT ). В Python так можно делать потому, что если первая часть сложного выражения возвращает ложь, то вторая часть уже не проверяется.
Если какая-либо клавиша была нажата, то проверяется, какая именно. В данном случае обрабатываются только две клавиши. В зависимости от этого меняется значение координаты x .
Проблема данного кода в том, что при выполнении программы, чтобы круг двигался, надо постоянно нажимать и отжимать клавиши. Если просто зажать их на длительный период, то объект не будет постоянно двигаться. Он сместиться только один раз на 3 пикселя.
Так происходит потому, что событие нажатия на клавишу происходит один раз, сколь долго бы ее не держали. Это событие было забрано из очереди функцией get() и обработано. Его больше нет. Поэтому приходится генерировать новое событие, еще раз нажимая на клавишу.
Как быть, если по логике вещей надо, чтобы шар двигался до тех пор, пока клавиша зажата? Когда же она отпускается, шар должен останавливаться. Первое, что надо сделать, – это перенести изменение координаты x в основную ветку главного цикла while . В таком случае на каждой его итерации координата будет меняться, а значит шар двигаться постоянно.
Во-вторых, в цикле обработки событий нам придется следить не только за нажатием клавиши, но и ее отжатием. Когда клавиша нажимается, какая-либо переменная, играющая роль флага, должна принимать одно значение, когда клавиша отпускается эта же переменная должна принимать другое значение.
В основном теле while надо проверять значение этой переменной и в зависимости от него менять или не менять значение координаты.
import pygame import sys FPS = 60 W = 700 # ширина экрана H = 300 # высота экрана WHITE = (255, 255, 255) BLUE = (0, 70, 225) RIGHT = "to the right" LEFT = "to the left" STOP = "stop" sc = pygame.display.set_mode((W, H)) clock = pygame.time.Clock() # координаты и радиус круга x = W // 2 y = H // 2 r = 50 motion = STOP while 1: for i in pygame.event.get(): if i.type == pygame.QUIT: sys.exit() elif i.type == pygame.KEYDOWN: if i.key == pygame.K_LEFT: motion = LEFT elif i.key == pygame.K_RIGHT: motion = RIGHT elif i.type == pygame.KEYUP: if i.key in [pygame.K_LEFT, pygame.K_RIGHT]: motion = STOP sc.fill(WHITE) pygame.draw.circle(sc, BLUE, (x, y), r) pygame.display.update() if motion == LEFT: x -= 3 elif motion == RIGHT: x += 3 clock.tick(FPS)
Использовать константы не обязательно, можно сразу присваивать строки или даже числа (например, motion = 1 обозначает движение вправо, -1 – влево, 0 – остановка). Однако константы позволяют легче понимать и обслуживать в дальнейшем код, делают его более информативным. Лучше привыкнуть к такому стилю.
Должно проверяться отжатие только двух клавиш. Если проверять исключительно KEYUP без последующей конкретизации, то отжатие любой клавиши приведет к остановке, даже если в это время будет по-прежнему зажиматься клавиша влево или вправо. Выражение i.key in [pygame.K_LEFT, pygame.K_RIGHT] обозначает, что если значение i.key совпадает с одним из значений в списке, то все выражение возвращает истину.
На самом деле существует способ по-проще. В библиотеке pygame с событиями работает не только модуль event . Так модуль pygame.key включает функции, связанные исключительно с клавиатурой. Здесь есть функция pygame.key.get_pressed() , которая возвращает кортеж двоичных значений. Индекс каждого значения соответствует своей клавиатурной константе. Само значение равно 1, если клавиша нажата, и 0 – если не нажата.
Эта функция подходит не для всех случаев обработки клавиатурных событий, но в нашем подойдет. Поэтому мы можем упростить код до такого варианта:
import pygame import sys FPS = 60 W = 700 # ширина экрана H = 300 # высота экрана WHITE = (255, 255, 255) BLUE = (0, 70, 225) sc = pygame.display.set_mode((W, H)) clock = pygame.time.Clock() # координаты и радиус круга x = W // 2 y = H // 2 r = 50 while 1: for i in pygame.event.get(): if i.type == pygame.QUIT: sys.exit() sc.fill(WHITE) pygame.draw.circle(sc, BLUE, (x, y), r) pygame.display.update() keys = pygame.key.get_pressed() if keys[pygame.K_LEFT]: x -= 3 elif keys[pygame.K_RIGHT]: x += 3 clock.tick(FPS)
Можно сказать, вызов get_pressed() снимает «маску» зажатых клавиш. Мы ее снимаем на каждой итерации главного цикла. Это даже не регистрация событий как таковых.
Выражение типа keys[pygame.K_LEFT] извлекает значение из кортежа по индексу, значение которого записано в константе K_LEFT . Если извлеченное значение True , то координата меняется.
Если необходимо, чтобы событие обрабатывалось при нажатии двух и более клавиш, то работает такое логическое выражение: keys[pygame.K_LEFT] and keys[pygame.K_a] (одновременное нажатие стрелки ‘влево’ и буквы ‘a’). Однако если нужно задействовать не обычные клавиши, а модификаторы, то данный номер не проходит.
В таком случае можно вернуться к первому варианту – перебирать события в цикле for :
. elif i.type == pygame.KEYDOWN: if i.key == pygame.K_LEFT and\ (i.mod & pygame.KMOD_SHIFT): motion = LEFT .
Здесь при if будет True , если перед нажатием стрелки был зажат левый Shift . Причем обратная последовательность: сначала зажать стрелку, потом Shift не сработает. Видимо модификаторы обрабатываются библиотекой pygame несколько отлично от обычных клавиш. Допустим, если при зажатии обычных клавиш генерируется только одно событие, то для модификаторов они генерируются постоянно или хранятся до отпускания в другой очереди.
Таким образом, если первым зажимается K_LEFT , то событие сразу обрабатывается. При этом в i.mod записывается отсутствие модификатора. Поэтому условие не срабатывает.
Если же первым зажимается модификатор, то это событие не теряется и позволяет условию при if выполнится в случае нажатия при этом обычной клавиши.
Весь перечень констант pygame, соответствующих клавишам клавиатуры, смотрите в документации: https://www.pygame.org/docs/ref/key.html
Практическая работа
Измените приведенную в уроке программу так, чтобы круг с той же скоростью, т. е. постепенно, возвращался назад в исходную точку, когда клавиша отпускается.
Курс с примерами решений практических работ:
pdf-версия
X Скрыть Наверх
Pygame. Введение в разработку игр на Python
Как научить Python использовать клавиатуру и мышь. Часть 1

В любой работе рано или поздно наступает момент, когда на компьютере нужно выполнять монотонные задачи, повторяя одни и те же действия из раза в раз. Кажется, что это можно было бы легко автоматизировать, ведь алгоритм прост и понятен, но на практике оказывается, что подходящий инструмент для такой автоматизации найти трудно. Но это не значит, что такой инструмент нельзя создать.
Цель: написать программу на языке Python для создания простых макросов, сначала записывающих, а после воспроизводящих действия клавиатуры и мыши. Управление программой будет происходить через графический интерфейс.
В начале потребуется библиотека для записи действий мыши и клавиатуры. В качестве таковой возьмём pynput.
Для отслеживания действий клавиатуры нужно инициализировать класс Listener. В качестве аргументов он принимает две функции: первая активируется, когда пользователь нажимает клавишу, а вторая – когда отпускает. Задействованные клавиши передаются этим функциям в аргументе. Далее нужно запустить саму прослушку клавиатуры. Всё это выглядит следующем образом:
from pynput import keyboard # Действие, когда пользователь нажимает клавишу на клавиатуре def on_press(key): print(f'Была нажата клавиша ') # Действие, когда пользователь отпускает клавишу на клавиатуре def on_release(key): print(f'Была отпущена клавиша ') # Инициализация прослушки клавиатуры keyboard_listener = keyboard.Listener( on_press=on_press, on_release=on_release ) # Старт прослушки клавиатуры keyboard_listener.start() # Здесь может выполняться другой код # Остановка прослушки клавиатуры keyboard_listener.stop()
Для прослушки мыши нужно выполнить похожие действия, отличие лишь в том, что Listener для мыши принимает три функции: для перемещения курсора, для нажатия клавиши мыши и для пролистывания. Единица координат курсора – пиксель, отсчет системы координат ведётся от левого верхнего угла монитора.
from pynput import mouse # Действие при движении курсора def on_move(x, y): print(f'Курсор переместился на позицию ' f' по горизонтали и по вертикали') # Действие при нажатии кнопки мыши def on_click(x, y, button, is_pressed): print(f'Была ' f'клавиша на позиции ' f' по горизонтали и по вертикали') # Действие при прокручивании def on_scroll(x, y, dx, dy): horizontal_scroll = '' if dx < 0: horizontal_scroll = 'влево' elif dx >0: horizontal_scroll = 'вправо' vertical_scroll = '' if dy < 0: vertical_scroll = 'вниз' elif dy >0: vertical_scroll = 'вверх' print(f'Была прокрутка ' f' на позиции ' f' по горизонтали и по вертикали') # Прослушка мыши mouse_listener = mouse.Listener( on_move=on_move, on_click=on_click, on_scroll=on_scroll ) # Старт прослушки мыши mouse_listener.start() # Здесь может выполняться другой код # Остановка прослушки мыши mouse_listener.stop()
Чтобы иметь возможность воспроизвести действия пользователя, прослушку клавиатуры и мыши нужно куда-то сохранить. Удобнее всего каждое действие записывать в словарь, где указывать устройство и что нажал пользователь. Все эти словари помещаем в список, который соответствует последовательности ввода.
Исходя из этого, получается следующая функция:
# Последовательность действий клавиатуры и мыши track = [] # Добавление новых действий клавиатуры и мыши # device - название контроллера ('keyboard', 'mouse') # action - действие ('press', 'release', 'move', 'scroll') # kwargs - все остальные параметры def add_action(device, action, **kwargs): if action not in ['press', 'release', 'move', 'scroll']: raise ValueError('Wrong action name.') if device == 'keyboard': # Если был ввод с клавиатуры, то просто перечисляем параметры track.append(< 'device': device, 'action': action, 'key': kwargs['key'] >) elif device == 'mouse': # Если был ввод с мыши, то сначала указываем положение курсора action_dict = < 'device': device, 'action': action, 'x': kwargs['x'], 'y': kwargs['y'] ># а после добавляем дополнительные параметры # в зависимости от действия if action == 'press' or action == 'release': action_dict['key'] = kwargs['key'] if action == 'scroll': action_dict['dx'] = kwargs['dx'] action_dict['dy'] = kwargs['dy'] self.track.append(action_dict)
А чтобы имитировать действия клавиатуры или мыши нужно использовать класс Controller из той же библиотеки pynput. Если исходить из того способа записи прослушки, что описан чуть выше, то функция для имитации будет иметь следующий вид:
from pynput import keyboard, mouse def run(): keyboard_controller = keyboard.Controller() mouse_controller = mouse.Controller() for t in self.track: time.sleep(0.1) # Действия клавиатуры if t['device'] == 'keyboard': # Нажатие клавиши клавиатуры if t['action'] == 'press': keyboard_controller.press(t['key']) # Отпуск клавиши клавиатуры elif t['action'] == 'release': keyboard_controller.release(t['key']) # Действия мыши if t['device'] == 'mouse': # Движение мыши mouse_controller.move( t['x'] - mouse_controller.position[0], t['y'] - mouse_controller.position[1] ) # Прокручивание колёсика if t['action'] == 'scroll': mouse_controller.scroll(t['dx'], t['dy']) # Нажатие кнопки мыши elif t['action'] == 'press': mouse_controller.press(t['key']) # Отпуск кнопки мыши elif t['action'] == 'release': mouse_controller.release(t['key'])
Чтобы не переполнять текст вставками кода, полная версия с использованием библиотеки pynput для прослушки и имитации клавиатуры или мыши расположена в репозитории github, ссылка на который находится в конце поста.
Единственное, что стоит отметить – это остановка прослушки при нажатии на правый shift. Клавишу можно выбрать любую, но так как правый shift используется реже, то удобнее использовать его. В коде это выглядит так:
def on_press(key): if key == keyboard.Key.shift_r: keyboard_listener.stop() mouse_listener.stop() return .
Теперь, для удобства восприятия, будет создан простой интерфейс с использованием библиотеки PySimpleGUI. В этом интерфейсе будут отображаться записанные действия пользователя, а также кнопки для старта записи или запуска имитации. Чтобы создать окно, с которым можно взаимодействовать, нужно инициализировать класс Window, передав в него двумерный список layout, представляющий собой взаимное расположение элементов:
import PySimpleGUI as psg # Элементы интерфейса layout = [ # Клавиши для изменения последовательности записанных действий [psg.Button('Up'), psg.Button('Down')], # Дерево для отображения самих записанных действий [psg.Tree(data=psg.TreeData(), key='Keys tree', headings=[])], # Кнопки для управления записью [psg.Button('Run'), psg.Button('Record')] ] # Создание окна wnd = psg.Window('Holop', layout, size=(500, 500))
Перехват нажатий осуществляется в бесконечном цикле, выйти из которого можно только тогда, когда пользователь закроет окно интерфейса:
while True: # Ожидание события окна event, values = wnd.read() # Выбор действия в зависимости от нажатой кнопки if event == psg.WINDOW_CLOSED: # Выход break elif event == 'Up': # Поднять выбранные элементы replace_elem(wnd.Element('Keys tree'), 'up') elif event == 'Down': # Опустить выбранные элементы replace_elem(wnd.Element('Keys tree'), 'down') elif event == 'Run': # Запустить имитацию действий клавиатуры и мыши run() elif event == 'Record': # Запустить прослушку клавиатуры и мыши start_record() wnd.close()
Как производится запись и имитация действий клавиатуры и мыши рассказано выше, а вот для перемещения элементов используется следующий код:
# Поднимает или опускает выбранные элементы def replace_elem(tree, direction): # Список выбранных элементов select_elems = tree.Widget.selection() # Если ни один элемент не выбран, то выход if len(select_elems) == 0: return # Получение основных элементов дерева treedata = tree.TreeData tree_root = treedata.tree_dict[''] # Перемещение всех выбранных элементов for s_e in select_elems: # Получение отмеченного элемента elem = treedata.tree_dict[tree.IdToKey[s_e]] ind = tree_root.children.index(elem) # Перемещение этого элемента if direction == 'up' and ind >= 0: tree_root.children[ind-1], tree_root.children[ind] =\ tree_root.children[ind], tree_root.children[ind-1] track[ind-1], track[ind] = track[ind], track[ind-1] elif direction == 'down' and ind < len(tree_root.children): tree_root.children[ind], tree_root.children[ind+1] =\ tree_root.children[ind+1], tree_root.children[ind] track[ind], track[ind+1] = track[ind+1], track[ind] # Обновление дерева tree.update(values=treedata)
После запуска кода перед нами появляется окно, с которым можно взаимодействовать:

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