2014-03-14 3 views
20

내 로컬 시스템이 화살표 키에 할당 한 값, 특히 Python에서 값을 찾으려고합니다. 나는이 작업을 수행하기 위해 다음 스크립트를 사용하고 있습니다 :파이썬에서 화살표 키 값 찾기 : 왜 그들은 트리플입니까?

$ python getchar.py 
you pressed 27 
you pressed 91 
you pressed 65 
you pressed 27 
you pressed 91 
you pressed 66 
you pressed 27 
you pressed 91 
you pressed 67 
you pressed 27 
you pressed 91 
you pressed 68 

이 그것을 제안하기 때문에 예외적이다 : 나는 스크립트를 실행하고, 나에게이 출력을 준 DOWN RIGHT LEFT, 최대 히트 그런

import sys,tty,termios 
class _Getch:  
    def __call__(self): 
      fd = sys.stdin.fileno() 
      old_settings = termios.tcgetattr(fd) 
      try: 
       tty.setraw(sys.stdin.fileno()) 
       ch = sys.stdin.read(1) 
      finally: 
       termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) 
      return ch 

def get(): 
    inkey = _Getch() 
    while(1): 
      k=inkey() 
      if k!='':break 
    print 'you pressed', ord(k) 

def main(): 
    for i in range(0,25): 
     get() 

if __name__=='__main__': 
    main() 

화살표 키를 누를 때마다 get()의 세 인스턴스를 사용하기 때문에 화살표 키가 내 시스템에 triple (27-91-6x)의 형식으로 등록됩니다. 비교 누르면 A, B, C와 CTRL-C는 제공 : 내 화살표 키의 값이 트리플로 저장하는 것 왜

you pressed 97 
you pressed 98 
you pressed 99 
you pressed 3 

는 사람이 나에게 설명 할 수 있습니까? 왜 이래? 이것은 모든 플랫폼에서 동일합니까? (데비안 리눅스를 사용하고 있습니다.) 그렇지 않다면 화살표 키 값을 어떻게 저장해야합니까?

최종 목표는 화살표 키를 올바르게 인식하고 화살표 키를 눌렀을 때 기능을 수행해야하는 프로그램을 작성하려고한다는 것입니다.

+0

키보드로 전송되는 이스케이프 코드에 대한 명확한 섹션이 없더라도 [ANSI 이스케이프 코드] (http://en.wikipedia.org/wiki/ANSI_escape_code)를 제안합니다. 그들의 형식은 프로그램에서 터미널로 보낸 것과 동일합니다. –

+0

이것은 관련이있는 것처럼 보입니다 : http://stackoverflow.com/questions/4130048/recognizing-arrow-keys-with-stdin – Newb

+0

왜'getch' 함수 대신에'__call__' 메쏘드가있는'_Getch' 클래스가 있습니까 ? – user2357112

답변

22

내가 알아 냈다고 생각합니다.

here에서 각 화살표 키는 고유 한 ANSI 이스케이프 코드로 나타났습니다. 그런 다음 ANSI 이스케이프 코드가 시스템 및 응용 프로그램에 따라 다르다는 것을 알았습니다. 터미널에서 cat을 누르고 위쪽 화살표를 누르면 \033[A 등으로 보입니다. [A은 동일하게 유지됩니다. 앞의 Escape에 대한 코드는 16 진수 (x로 시작), 8 진수 (0으로 시작) 또는 10 진수 (숫자로 된 리드 없음) 일 수 있습니다.

그런 다음 파이썬 콘솔을 열고 이전에받은 트리플을 연결하여 문자 값을 찾으려고했습니다. 그 결과, chr(27)\x1b으로, chr(91)[으로, chr65,66,67,68으로 각각 A,B,C,D으로 반환되었습니다. 그렇다면 그것은 분명했습니다 : \x1b는 탈출 코드였습니다!

그런 다음 ANSI에서 3 중 문자로 표시되는 화살표 키는 물론 3 자로 표시되므로 한 번에 3 자씩 읽으려면 코드를 수정해야한다고 언급했습니다. 다음은 결과입니다

import sys,tty,termios 
class _Getch: 
    def __call__(self): 
      fd = sys.stdin.fileno() 
      old_settings = termios.tcgetattr(fd) 
      try: 
       tty.setraw(sys.stdin.fileno()) 
       ch = sys.stdin.read(3) 
      finally: 
       termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) 
      return ch 

def get(): 
     inkey = _Getch() 
     while(1): 
       k=inkey() 
       if k!='':break 
     if k=='\x1b[A': 
       print "up" 
     elif k=='\x1b[B': 
       print "down" 
     elif k=='\x1b[C': 
       print "right" 
     elif k=='\x1b[D': 
       print "left" 
     else: 
       print "not an arrow key!" 

def main(): 
     for i in range(0,20): 
       get() 

if __name__=='__main__': 
     main() 
+0

getch() 함수에 여러 ASCII 값 (이스케이프 및 다음 문자)을 전달할 수있는 main에서 루프를 사용하는 것이 좋습니다. 그래도 _Getch 함수에서 for 루프를 사용하면 더 효율적입니다. – JFA

+0

ctrl + c (및 다른 신호)에 의해 중단 될 수 있습니까? – ThorSummoner

+0

@ThorSummoner 예. get() 함수를 사용하면 다른 elif를 추가하고 ctrl + c와 같은 신호를 볼 수 있습니다. 그러나이를 수행하는 더 쉬운 방법이 있습니다. – Newb

3

나는 맥을 사용하고 난 다음 코드를 사용하고는 잘 작동 : 을 나는 0, 1, 2, 3 (위, 아래, 왼쪽으로 내 화살표 키에 대한 값을 가지고 , 오른쪽) : 항상 ESC 키의 코드 27을 기억하는 것이 좋습니다. 감사합니다.

while True: 
    key = cv2.waitKey(1) & 0xFF 

    # if the 'ESC' key is pressed, Quit 
    if key == 27: 
     quit() 
    if key == 0: 
     print "up" 
    elif key == 1: 
     print "down" 
    elif key == 2: 
     print "left" 
    elif key == 3: 
     print "right" 
    # 255 is what the console returns when there is no key press... 
    elif key != 255: 
     print(key)