Не могу считывать сразу и нажатия и отжатия клавиш python keyboard
Недавно решил начать делать свою игру с нуля. Первым делом решил сделать систему биндинга клавиш. Легко сделал 2 типа - [одиночное нажатие,переключение]. Однако с созданием самого ходового типа - "удержания" появилась проблема. Я не могу сделать сразу отслеживание и нажатия и отжатия (новые потоки попросту не создаются. посмотрел это через threading.active_count()). Как я могу это починить. У меня есть идея с потиковой проверкой (отслеживание клавиатуры идет в цикле с ожиданием 0.1 секунду. в один тик можно проверять нажатие а в следующий отжатие и так поочередно) Весь код достаточно большой, так что приведу именно цикл.
f_Kb - класс, в котором я написал методы check_button_press и check_button_release, которые соответственно проверяют нажатие и отжатие заданной клавиши.
i = 0
while i < 100/0.1: #цикл идет 100 секунд
z = 0
while z < len(f_Kb.type): обнуление всех кулдаунов (для предотвращения ложных, повторных считываний)
f_Kb.cooldowns[z] = False
z += 1
z = 0
while z < len(f_Kb.online_keys): #запуск функций у активных биндов
f_Kb.behaviours[f_Kb.get_index_by_object(f_Kb.online_keys[z],f_Kb.keys)]()
z += 1
#...............проблемное место.................
keyboard.on_release(f_Kb.check_button_press)
keyboard.on_press(f_Kb.check_button_release)
i += 1
как я могу реализовать свою идею?
Ответы (1 шт):
Интересная зада, решил для вас сделать небольшой пример:
import keyboard
import threading
import queue
import time
class KeyTracker:
def __init__(self, callback):
self.pressed_keys = set()
self.callback = callback
self.queue = queue.Queue()
keyboard.hook(self.key_event)
self.callback_thread = threading.Thread(target=self.queue_callback)
self.callback_thread.start()
def key_event(self, event):
if event.event_type == keyboard.KEY_DOWN:
if event.name not in self.pressed_keys:
self.pressed_keys.add(event.name)
self.queue.put(self.pressed_keys)
print(f"Нажата клавиша: {event.name}")
elif event.event_type == keyboard.KEY_UP:
if event.name in self.pressed_keys:
self.pressed_keys.remove(event.name)
self.queue.put(self.pressed_keys)
print(f"Отпущена клавиша: {event.name}")
def queue_callback(self):
while True:
pressed_keys = self.queue.get()
if pressed_keys is None:
break
self.callback(pressed_keys)
def stop(self):
self.queue.put(None)
self.callback_thread.join()
def start(self):
try:
keyboard.wait('esc')
except KeyboardInterrupt:
pass
finally:
self.stop()
threads = {}
def pressed_keys(keys):
print(f"Активные клавиши: {keys}")
if 'z' in keys and 'z' not in threads:
threads['z'] = threading.Thread(target=z_pressed, args=(keys,))
threads['z'].start()
if 'x' in keys and 'x' not in threads:
threads['x'] = threading.Thread(target=x_pressed, args=(keys,))
threads['x'].start()
keys_v_b = {'v', 'b'}
if keys_v_b.issubset(keys) and 'v+b' not in threads:
threads['v+b'] = threading.Thread(target=v_b_pressed, args=(keys,))
threads['v+b'].start()
def z_pressed(keys):
while 'z' in keys:
print("Зажата Z")
time.sleep(0.2)
del threads['z']
def x_pressed(keys):
while 'x' in keys:
print("Зажата x")
time.sleep(0.2)
del threads['x']
def v_b_pressed(keys):
while all(key in keys for key in ('v', 'b')):
print("Зажата v+b")
time.sleep(0.2)
del threads['v+b']
if __name__ == "__main__":
tracker = KeyTracker(pressed_keys)
tracker.start()