키 누르기를 감지하는 방법은 무엇입니까?
저는 파이썬에서 스톱워치 유형의 프로그램을 만들고 있는데 키가 눌렸는지 감지하는 방법(예: 일시 중지 및 중지)을 알고 싶습니다.raw_input
실행을 계속하기 전에 사용자의 입력을 기다립니다.
잠깐 동안 이걸 어떻게 하는지 아는 사람?
저는 이 크로스 플랫폼을 만들고 싶지만, 그것이 불가능하다면, 제 주요 개발 목표는 리눅스입니다.
Python에는 많은 기능이 있는 키보드 모듈이 있습니다.다음 명령을 사용하여 설치합니다.
pip3 install keyboard
그런 다음 다음과 같은 코드로 사용합니다.
import keyboard # using module keyboard
while True: # making a loop
try: # used try so that if user pressed other than the given key error will not be shown
if keyboard.is_pressed('q'): # if key 'q' is pressed
print('You Pressed A Key!')
break # finishing the loop
except:
break # if user pressed a key other than the given key the loop will break
창밖에 있으면서 제대로 된 답을 찾기 위해 고군분투하는 사람들을 위해 여기 내 것이 있습니다: pinput.
from pynput.keyboard import Key, Listener
def on_press(key):
print('{0} pressed'.format(
key))
def on_release(key):
print('{0} 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()
위의 기능은 'esc' 키를 놓으면 어떤 키를 누르든 인쇄하고 'esc' 키를 놓으면 작업을 시작합니다.키보드 설명서는 다양한 용도로 제공됩니다.
Markus von Broady는 다음과 같은 잠재적인 문제를 강조했습니다.이 대답은 현재 창에서 이 스크립트를 활성화할 필요가 없습니다. 창에 대한 해결책은 다음과 같습니다.
from win32gui import GetWindowText, GetForegroundWindow
current_window = (GetWindowText(GetForegroundWindow()))
desired_window_name = "Stopwatch" #Whatever the name of your window should be
#Infinite loops are dangerous.
while True: #Don't rely on this line of code too much and make sure to adapt this to your project.
if current_window == desired_window_name:
with Listener(
on_press=on_press,
on_release=on_release) as listener:
listener.join()
모듈로 더 많은 일을 할 수 있습니다.다음을 사용하여 이 모듈을 설치할 수 있습니다.pip install keyboard
다음은 몇 가지 방법입니다.
방법 #1:
기능 사용:
import keyboard
while True:
if keyboard.read_key() == "p":
print("You pressed p")
break
키를 누르면 고리가 끊어집니다.
방법 #2:
함수 사용:
import keyboard
keyboard.wait("p")
print("You pressed p")
코드를 누른 후 계속 누를 때까지 기다립니다.
방법 #3:
기능 사용:
import keyboard
keyboard.on_press_key("p", lambda _:print("You pressed p"))
콜백 기능이 필요합니다.저는 용한사를 요._
키보드 기능이 키보드 이벤트를 해당 기능으로 되돌리기 때문입니다.
일단 실행되면 키를 누르면 기능이 실행됩니다.다음 라인을 실행하여 모든 후크를 중지할 수 있습니다.
keyboard.unhook_all()
방법 #4:
이 방법은 이미 사용자 8167727에 의해 답변되었지만 저는 그들이 만든 코드에 동의하지 않습니다.이 기능은 다음과 같은 방식으로 사용됩니다.
import keyboard
while True:
if keyboard.is_pressed("p"):
print("You pressed p")
break
누르면 루프가 끊어집니다.
방법 #5:
사용할 수도 있습니다.를 누를 때까지 눌렀다 놓은 모든 키가 기록됩니다.escape
키또사가정키에서 한 키.until
인수를 지정하고 요소 목록을 반환합니다.
import keyboard
keyboard.record(until="p")
print("You pressed p")
주의:
keyboard
전체 OS에서 키프레스를 읽습니다.keyboard
에서 합니다.
OP가 raw_input에 대해 언급했듯이, 그것은 그가 CLI 솔루션을 원한다는 것을 의미합니다.리눅스: 저주가 원하는 것입니다(윈도우즈 PDCurs).Curses는 CLI 소프트웨어를 위한 그래픽 API로, 주요 이벤트를 탐지하는 것 이상의 것을 달성할 수 있습니다.
이 코드는 새 줄을 누를 때까지 키를 감지합니다.
import curses
import os
def main(win):
win.nodelay(True)
key=""
win.clear()
win.addstr("Detected key:")
while 1:
try:
key = win.getkey()
win.clear()
win.addstr("Detected key:")
win.addstr(str(key))
if key == os.linesep:
break
except Exception as e:
# No input
pass
curses.wrapper(main)
Windows의 경우msvcrt
다음과 같이:
import msvcrt
while True:
if msvcrt.kbhit():
key = msvcrt.getch()
print(key) # just to show the result
이 코드를 사용하여 누른 키를 찾습니다.
from pynput import keyboard
def on_press(key):
try:
print('alphanumeric key {0} pressed'.format(
key.char))
except AttributeError:
print('special key {0} pressed'.format(
key))
def on_release(key):
print('{0} released'.format(
key))
if key == keyboard.Key.esc:
# Stop listener
return False
# Collect events until released
with keyboard.Listener(
on_press=on_press,
on_release=on_release) as listener:
listener.join()
질문 자체에 대한 neoDev의 언급은 놓치기 쉬우나 여기서 어떤 답변에도 언급되지 않은 해결책과 연결됩니다.
가올필없다니습가요를 가져올 필요가 .keyboard
이 용액으로.
이 다른 질문에서 복사된 솔루션, 모든 크레딧은 @neoDev.
이것은 macOS Sierra, Python 2.7.10 및 3.6.3에서 작동했습니다.
import sys,tty,os,termios def getkey(): old_settings = termios.tcgetattr(sys.stdin) tty.setcbreak(sys.stdin.fileno()) try: while True: b = os.read(sys.stdin.fileno(), 3).decode() if len(b) == 3: k = ord(b[2]) else: k = ord(b) key_mapping = { 127: 'backspace', 10: 'return', 32: 'space', 9: 'tab', 27: 'esc', 65: 'up', 66: 'down', 67: 'right', 68: 'left' } return key_mapping.get(k, chr(k)) finally: termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_settings) try: while True: k = getkey() if k == 'esc': quit() else: print(k) except (KeyboardInterrupt, SystemExit): os.system('stty sane') print('stopping.')
PyGame을 사용하여 창을 만들면 주요 이벤트를 얻을 수 있습니다.
는 p
:
import pygame, sys
import pygame.locals
pygame.init()
BLACK = (0,0,0)
WIDTH = 1280
HEIGHT = 1024
windowSurface = pygame.display.set_mode((WIDTH, HEIGHT), 0, 32)
windowSurface.fill(BLACK)
while True:
for event in pygame.event.get():
if event.key == pygame.K_p: # replace the 'p' to whatever key you wanted to be pressed
pass #Do what you want to here
if event.type == pygame.locals.QUIT:
pygame.quit()
sys.exit()
ssh: ssh 키보드를 통해서도 작동하는 비루트 버전입니다.설치 대상pip install sshkeyboard
,
다음과 같은 스크립트를 작성합니다.
from sshkeyboard import listen_keyboard
def press(key):
print(f"'{key}' pressed")
def release(key):
print(f"'{key}' released")
listen_keyboard(
on_press=press,
on_release=release,
)
다음과 같이 인쇄됩니다.
'a' pressed
'a' released
때A
키를 누릅니다. ESC
key는 기본적으로 수신을 종료합니다.
예를 들어, 욕, tkinter, getch보다 코딩이 덜 필요합니다.그리고 키보드 모듈처럼 루트 액세스가 필요하지 않습니다.
저는 이 게시물을 기반으로 이런 종류의 게임을 만들었습니다(msvcr 라이브러리와 Python 3.7 사용).
누른 키를 감지하는 게임의 주요 기능은 다음과 같습니다.
import msvcrt
def _secret_key(self):
# Get the key pressed by the user and check if he/she wins.
bk = chr(10) + "-"*25 + chr(10)
while True:
print(bk + "Press any key(s)" + bk)
#asks the user to type any key(s)
kp = str(msvcrt.getch()).replace("b'", "").replace("'", "")
# Store key's value.
if r'\xe0' in kp:
kp += str(msvcrt.getch()).replace("b'", "").replace("'", "")
# Refactor the variable in case of multi press.
if kp == r'\xe0\x8a':
# If user pressed the secret key, the game ends.
# \x8a is CTRL+F12, that's the secret key.
print(bk + "CONGRATULATIONS YOU PRESSED THE SECRET KEYS!\a" + bk)
print("Press any key to exit the game")
msvcrt.getch()
break
else:
print(" You pressed:'", kp + "', that's not the secret key(s)\n")
if self.select_continue() == "n":
if self.secondary_options():
self._main_menu()
break
만약 당신이 프로그램의 전체 소스 코드를 원한다면 당신은 그것을 보거나 GitHub에서 다운로드할 수 있습니다.
비밀 키 누르기는 다음과 같습니다.
Ctrl+F12
이것이 GUI 프로그램인지 아닌지는 언급하지 않지만 대부분의 GUI 패키지에는 키보드 입력을 캡처하고 처리하는 방법이 포함되어 있습니다.예를 들어 다음과 같이tkinter
(Py3에서는) 특정 이벤트에 바인딩한 다음 함수에서 처리할 수 있습니다.예:
import tkinter as tk
def key_handler(event=None):
if event and event.keysym in ('s', 'p'):
'do something'
r = tk.Tk()
t = tk.Text()
t.pack()
r.bind('<Key>', key_handler)
r.mainloop()
위의 내용을 사용하여 텍스트 위젯에 입력하면key_handler
사용자가 누르는 각 키(또는 거의 각 키)에 대해 루틴이 호출됩니다.
keyboard
패키지, 특히 Linux에서는 해당 패키지를 실행하려면 루트 권한이 필요하기 때문에 적합한 솔루션이 아닙니다.우리는 getkey 패키지로 이것을 쉽게 구현할 수 있습니다.이것은 C 언어 함수 getchar와 유사합니다.
설치:
pip install getkey
사용:
from getkey import getkey
while True: #Breaks when key is pressed
key = getkey()
print(key) #Optionally prints out the key.
break
누른 키를 반환하는 기능에 이것을 추가할 수 있습니다.
def Ginput(str):
"""
Now, this function is like the native input() function. It can accept a prompt string, print it out, and when one key is pressed, it will return the key to the caller.
"""
print(str, end='')
while True:
key = getkey()
print(key)
return key
다음과 같이 사용:
inp = Ginput("\n Press any key to continue: ")
print("You pressed " + inp)
저주 모듈이 그 일을 합니다.
터미널에서 다음 예제를 실행하여 테스트할 수 있습니다.
import curses
screen = curses.initscr()
curses.noecho()
curses.cbreak()
screen.keypad(True)
try:
while True:
char = screen.getch()
if char == ord('q'):
break
elif char == curses.KEY_UP:
print('up')
elif char == curses.KEY_DOWN:
print('down')
elif char == curses.KEY_RIGHT:
print('right')
elif char == curses.KEY_LEFT:
print('left')
elif char == ord('s'):
print('stop')
finally:
curses.nocbreak(); screen.keypad(0); curses.echo()
curses.endwin()
import cv2
key = cv2.waitKey(1)
이것은 열려 있는 CV 패키지에서 나온 것입니다.그delay
arg는 키를 누를 때까지 대기하는 시간(밀리초)입니다.이 경우 1ms입니다.문서에 따르면,pollKey()
기다리지 않고 사용할 수 있습니다.
다음은 차단 및 비차단을 모두 지원하는 교차 플랫폼 솔루션으로, 외부 라이브러리가 필요하지 않습니다.
import contextlib as _contextlib
try:
import msvcrt as _msvcrt
# Length 0 sequences, length 1 sequences...
_ESCAPE_SEQUENCES = [frozenset(("\x00", "\xe0"))]
_next_input = _msvcrt.getwch
_set_terminal_raw = _contextlib.nullcontext
_input_ready = _msvcrt.kbhit
except ImportError: # Unix
import sys as _sys, tty as _tty, termios as _termios, \
select as _select, functools as _functools
# Length 0 sequences, length 1 sequences...
_ESCAPE_SEQUENCES = [
frozenset(("\x1b",)),
frozenset(("\x1b\x5b", "\x1b\x4f"))]
@_contextlib.contextmanager
def _set_terminal_raw():
fd = _sys.stdin.fileno()
old_settings = _termios.tcgetattr(fd)
try:
_tty.setraw(_sys.stdin.fileno())
yield
finally:
_termios.tcsetattr(fd, _termios.TCSADRAIN, old_settings)
_next_input = _functools.partial(_sys.stdin.read, 1)
def _input_ready():
return _select.select([_sys.stdin], [], [], 0) == ([_sys.stdin], [], [])
_MAX_ESCAPE_SEQUENCE_LENGTH = len(_ESCAPE_SEQUENCES)
def _get_keystroke():
key = _next_input()
while (len(key) <= _MAX_ESCAPE_SEQUENCE_LENGTH and
key in _ESCAPE_SEQUENCES[len(key)-1]):
key += _next_input()
return key
def _flush():
while _input_ready():
_next_input()
def key_pressed(key: str = None, *, flush: bool = True) -> bool:
"""Return True if the specified key has been pressed
Args:
key: The key to check for. If None, any key will do.
flush: If True (default), flush the input buffer after the key was found.
Return:
boolean stating whether a key was pressed.
"""
with _set_terminal_raw():
if key is None:
if not _input_ready():
return False
if flush:
_flush()
return True
while _input_ready():
keystroke = _get_keystroke()
if keystroke == key:
if flush:
_flush()
return True
return False
def print_key() -> None:
"""Print the key that was pressed
Useful for debugging and figuring out keys.
"""
with _set_terminal_raw():
_flush()
print("\\x" + "\\x".join(map("{:02x}".format, map(ord, _get_keystroke()))))
def wait_key(key=None, *, pre_flush=False, post_flush=True) -> str:
"""Wait for a specific key to be pressed.
Args:
key: The key to check for. If None, any key will do.
pre_flush: If True, flush the input buffer before waiting for input.
Useful in case you wish to ignore previously pressed keys.
post_flush: If True (default), flush the input buffer after the key was
found. Useful for ignoring multiple key-presses.
Returns:
The key that was pressed.
"""
with _set_terminal_raw():
if pre_flush:
_flush()
if key is None:
key = _get_keystroke()
if post_flush:
_flush()
return key
while _get_keystroke() != key:
pass
if post_flush:
_flush()
return key
사용할 수 있습니다.key_pressed()
잠시 동안 루프 내부:
while True:
time.sleep(5)
if key_pressed():
break
특정 키를 확인할 수도 있습니다.
while True:
time.sleep(5)
if key_pressed("\x00\x48"): # Up arrow key on Windows.
break
다음을 사용하여 특수 키 확인print_key()
:
>>> print_key()
# Press up key
\x00\x48
또는 특정 키를 누를 때까지 기다립니다.
>>> wait_key("a") # Stop and ignore all inputs until "a" is pressed.
Pygame을 사용할 수 있습니다.
import pygame
while True:
keys = pygame.key.get_pressed()
if (keys[pygame.K_LEFT]):
pos_x -= 5
elif (keys[pygame.K_RIGHT]):
pos_x += 5
elif (keys[pygame.K_UP]):
pos_y -= 5
elif (keys[pygame.K_DOWN]):
pos_y += 5
저는 다음과 같은 경우까지 다양한 키 누름을 감지하는 방법을 찾고 있었습니다. Ctrl + C
다른 키 누르기를 듣고 그에 따라 응답하는 프로그램을 중단합니다.
다음 코드를 사용하여
while True:
if keyboard.is_pressed("down"):
print("Reach the bottom!")
if keyboard.is_pressed("up"):
print("Reach the top!")
if keyboard.is_pressed("ctrl+c"):
break
화살표를 아래로 누르거나 위쪽으로 누르면 프로그램에서 응답 텍스트를 계속 스팸으로 보냅니다.나는 그것이 while-loop에 있고, 비록 당신이 한 번만 눌렀지만, 그것이 여러 번 트리거될 것이기 때문에 믿었습니다(문서에 쓰여 있듯이, 나는 그것을 읽은 후에 이것을 알게 되었습니다.
그 순간, 저는 여전히 그 문서를 읽으러 가지 않았습니다, 저는 덧붙이려고 노력합니다.time.sleep()
while True:
if keyboard.is_pressed("down"):
print("Reach the bottom!")
time.sleep(0.5)
if keyboard.is_pressed("up"):
print("Reach the top!")
time.sleep(0.5)
if keyboard.is_pressed("ctrl+c"):
break
이렇게 하면 스팸 문제가 해결됩니다.
그러나 이것은 화살표 키를 매우 빠르게 탭하는 후속 방법으로는 그다지 좋지 않습니다. 프로그램이 오른쪽으로 0.5초 동안 절전 모드로 전환되므로 0.5초에 발생한 "키보드 이벤트"는 계산되지 않습니다.
그래서, 저는 계속해서 문서를 읽고 이 부분에서 이것을 하기 위한 아이디어를 얻습니다.
while True:
# Wait for the next event.
event = keyboard.read_event()
if event.event_type == keyboard.KEY_DOWN and event.name == 'down':
# do whatever function you wanna here
if event.event_type == keyboard.KEY_DOWN and event.name == 'up':
# do whatever function you wanna here
if keyboard.is_pressed("ctrl+c"):
break
이제, 잘 작동하고 있어요! TBH, 저는 예전에 그 문서를 깊이 파고들지는 않았지만, 내용을 정말 잊어버렸어요. 만약 당신이 비슷한 기능을 하는 더 좋은 방법을 알고 있거나 찾는다면, 저에게 알려주세요!
감사합니다, 앞으로 좋은 하루 보내시길 바랍니다!
언급URL : https://stackoverflow.com/questions/24072790/how-to-detect-key-presses
'programing' 카테고리의 다른 글
어떻게 하면 약속이 반복되지 않도록 제한할 수 있습니까? (0) | 2023.06.12 |
---|---|
MariaDB: 사례를 사용하여 수행된 작업과 요청 일치(합계 > 0) (0) | 2023.06.12 |
git pull이 "참조 확인 실패" "로컬 참조 업데이트 실패" (0) | 2023.06.12 |
Gradle 및 Android Studio를 통한 앱 구축 및 실행 속도가 Eclipse보다 느림 (0) | 2023.06.12 |
python 3을 사용하여 python 2 개체 선택 취소 (0) | 2023.06.07 |