본문 바로가기
프로그래밍 관련/PyQt

PyQt() Keyboard 이벤트, Keyboard인터럽트 pynput 라이브러리

by 존버매니아.임베디드 개발자 2021. 9. 16.
반응형

키보드로부터 입력을 받아서 인터럽트를 발생시키고 싶었다.

키보드 인풋을 받아오는 방법은 검색을 해보니 다양한게 나왔는데

일단 PyQt에서 자체적으로 지원하는 keyboad event 핸들러를 사용하는 방법이 있었다.

아래는 PyQt 가 제공하는 키보드 이벤트 핸들러 사용한 예시케이스이다.


1.PyQt가 제공하는 키보드 이벤트 핸들러 사용

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt

class MyWindow(QMainWindow):
         
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Test")
        self.setGeometry(1000, 200, 300, 300)

    def keyPressEvent(self, e): #키가 눌러졌을 때 실행됨
        if e.key() == Qt.Key_Escape:
            print("esc pressed")
        elif e.key() == Qt.Key_A:
            print("A is pressed)")
        else:
            print((e.key()))

    def keyReleaseEvent(self,e): #키를 누른상태에서 뗏을 때 실행됨
        print("kye is pressed:")
        print(e.key())
    


if __name__ == "__main__":
    app = QApplication(sys.argv)
    myWindow = MyWindow()
    myWindow.show()

    app.exec_()

코드 구현방법은 간단하다.

이름에서 유추가 가능할 텐데

키보드에 아무거나 키를 누르면 KeyPressEvent 메소드가 실행된다.

그리고 누르고 있던 키를 떼면 KeyReleaseEvent 메소드가 실행된다.

이 때 실행되는 메소드에 argument로 해당 키의 정보가 전달되는 형태이다.

 

한가지 유의할 점은 위 이벤트핸들러에서 받아오는 e 값은 아스키코드 값을 받아오는데

특수키인 shift, backspace, space, enter 키등등은 아스키코드 범위를 벗어나는 매우 큰 숫자가 나오더라.

특수키에 대한 처리 어떻게 해줄지 정의 필요 할 듯.(그 방법은 일단 나중에 알아보고. 우선 여기서는 패스)


2.pynput 라이브러리 사용

근데 여기서 문제가 있었다.

 

내가 하고싶은게 뭐였냐면 

 

PyQt로 만들어진 SW를 실행시킨 후, 이 SW를 활성화시키지 않은 상태에서 키보드 인풋을 받고 싶었다.

(예를 들어서 PyQt GUI SW를 실행시킨 상태에서, 이 sw는 작업표시줄에 최소화 시켜놓고 다른 프로그램을 활성화시킨 상태)

 

이 상태에서는 위의 이벤트 핸들러가 동작을 하지 않았다.

앞에서 살펴봤던 키보드 핸들러는 PyQt SW가 컴퓨터상에서 활성화 돼있을 때만 동작하고 있었다.

 

그래서 PyQt GUI SW가 비활성화 상태에서도 키보드 이벤트를 받을 수 있는 방법을 찾게되었고..

pynput 이라는 라이브러리를 알게되었다.

기본 라이브러리가 아니므로 pip install pynput 으로 설치를 해서 사용해야한다.

 

일단 기본 사용 형태를 보자.

 

from pynput import keyboard
    
def on_press(key):
        try:
            print(f'알파벳 \'{key.char}\' 눌림')
        except AttributeError:
            print(f'특수키 {key} 눌림')

def on_release(key):
    print(f'키보드 {key} 풀림')
    if key == keyboard.Key.esc:
        # esc 키에서 풀림
        return False

with keyboard.Listener(on_press=on_press, on_release=on_release) as listener:
    listener.join()

 

 

 

위 코드에서 with keyboard.Listner 라는 키워드가 정확히 뭐하는 키워드인지는 공부가 더 필요하다.

위의 코드만 놓고보면 while 루프 같은게 없으니까 SW 실행하면 그냥 꺼져야될 거 같은데

정확히 어떻게 돌아가고 있는진 모르겠는데 위 코드를 실행시키면 SW가 게속 돌면서

키보드 누르면 등록된 on_press 함수가 실행되고 ,키보드 눌렀다 떼면 on_release 함수가 실행된다.

 

이게 기초적인 pynput 라이브러리를 사용하는 예시이다.

이 SW의 경우 PyQt의 키보드이벤트리스너와 달리 파이썬 SW가 비활성화되어있어도 동작을 하더라.

 

다음으로, 이 pynput 라이브러리랑 PyQt를 같이 쓰는 예시를 알아보자.


3.pynput 라이브러리를 PyQt랑 같이 사용하기

2번에서 살펴본 것 처럼 코드를 입력하면..

listener.join() 을 호출하고나면 어딘가 루프에 빠지는거 같다.

그래서 저 뒤에 있는 코드 실행이 안된다.

 

그래서 PyQt랑 같이 쓰려고하는데 쓸 수가 없다.

 

내가 찾은 방법이 과연 최선의 방법인지 의문인데 내가 찾은 방법은..

 

PyQt 안에서 쓰레드를 하나 추가로 만들고

이 쓰레드 안에서 pynput listner를 등록해서 사용하는 방식이다.

 

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt
from PyQt5.QtCore import QThread
from pynput import keyboard

class MyThread(QThread):
    cnt=0
    running= False

    def __init__(self):
        super().__init__()  
  
    def on_press(self,key):
        try:
            print(f'알파벳 \'{key.char}\' 눌림')
        except AttributeError:
            print(f'특수키 {key} 눌림')
 
    def on_release(self,key):
        print(f'키보드 {key} 풀림')
        if key == keyboard.Key.esc:
            # esc 키에서 풀림
            return False

    def run(self):
        with keyboard.Listener(on_press=self.on_press, on_release=self.on_release) as listener:
         listener.join()


class MyWindow(QMainWindow):
         
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Test")
        self.setGeometry(1000, 200, 300, 300)

        self.Thread1 = MyThread()
        self.Thread1.start()
    

if __name__ == "__main__":
    app = QApplication(sys.argv)
    myWindow = MyWindow()
    myWindow.show()

    app.exec_()

 

 

반응형

'프로그래밍 관련 > PyQt' 카테고리의 다른 글

PyQt - TreeWidget  (0) 2021.10.21
PyQt. Qt Designer 개요.사용방법  (1) 2021.10.19
PyQt(4) 쓰레드 사용하기  (0) 2021.09.14
PyQt(3) 버튼 이벤트 만들기  (0) 2021.09.13
PyQt(2) 타이머 인터럽트 만들기  (0) 2021.09.13