Qt Mouse Wheel Event 처리하기
개요
이번 시간에는 다양한 곳에서 사용되는 마우스 휠 이벤트 (Wheel Event)를 Python +PyQt5에서 어떻게 감지하고 활용하는지 살펴보겠습니다.
마우스 휠 이벤트가 필요한 대표적인 경우는 다음과 같습니다.
화면 이동, 웹페이지 업, 다운 처리
이미지 줌인, 줌 아웃
먼저 완성된 결과물을 먼저 살펴보면 아래와 같습니다.
[마우스 휠 이벤트 처리] |
아래와 같은 순서로 진행됩니다.
1. 빈 위젯을 하나 생성
2. Ctrl 키 눌러진 상태에서 휠 이벤트가 발생 (줌인, 아웃으로 처리)
3. Ctrl 키 떨어진 상태에서 휠 이벤트가 발생 (일반적인 스크롤로 처리)
4. 휠 이벤트 발생시 Ctrl 키 여부를 감지, 각 변수에 저장 후 출력
사실 줌이나 일반스크롤로 처리하나 둘 다 개념은 같지만 줌의
경우는 휠 이벤트시(Ctrl O) 1씩 변화량을 가져가고 스크롤(Ctrl X) 은 좀 더
변화량이 크게 적용해 보았습니다.
개발 환경
-
Windows 10 Pro 64bit
Python 3.8.8 64bit, Pycharm 2021.1
PyQt 5.15.3
소스코드
from PyQt5.QtWidgets import QApplication, QWidget from PyQt5.QtGui import QPainter, QFont from PyQt5.QtCore import Qt, QPointF import sys QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True) class Form(QWidget): def __init__(self): super().__init__() self.setWindowTitle('Mouse Wheel Event') self.bCtrl = False self.deg = QPointF() self.zoom = QPointF() def paintEvent(self, e): qp = QPainter() qp.begin(self) f = QFont('arial', 20) qp.setFont(f) ctrltxt = f'Ctrl Key Pressed:{self.bCtrl}' zoomtxt = f'Zoom X:{self.zoom.x()}, Zoom Y:{self.zoom.y()}' degtxt = f'Deg X:{self.deg.x()}, Deg Y:{self.deg.y()}' qp.drawText(self.rect(), Qt.AlignCenter, ctrltxt+'\n'+zoomtxt+'\n'+degtxt) qp.end() def keyPressEvent(self, e): if e.key() == Qt.Key_Control: self.bCtrl = True self.update() def keyReleaseEvent(self, e): if e.key() == Qt.Key_Control: self.bCtrl = False self.update() def wheelEvent(self, e): if self.bCtrl: self.zoom += e.angleDelta() / 120 else: self.deg += e.angleDelta() / 8 self.update() if __name__ == '__main__': app = QApplication(sys.argv) w = Form() w.show() sys.exit(app.exec_())
[라인 1~6]
필요한 모듈을 불러오고, 4K 모니터를 위한 해상도 설정을 진행합니다.
[라인 8~15]
QWidge에서 상속받은 Form Class의 선언과 생성자 함수입니다.
Ctrl키의 눌러짐을 감지할 bool type 변수, 마우스 휠 이벤트를 2가지 타입 (줌, 스크롤)으로 저장할 QPointF type 변수를 선언합니다.
[라인 17~28]
QWidet의 paintEvent() 에 대한 오버라이딩이며 위젯을 새로 그릴 필요가 있을때 마다 호출되는 함수입니다.
QPainter 객체를 생성하고 Ctrl 키 눌러짐 여부, Zoom값, 스크롤 값(Deg)을 fstring으로 정리해 화면에 출력합니다.
[라인 30~33]
QWidget의 keyPressEvent() 에 대한 오버라이딩이며 위젯에 키보드가 눌러진 경우 호출되는 함수입니다.
Ctrl 키가 눌러진 경우 self.bCtrl 변수를 참으로 설정합니다.
self.update()는 QWidget의 paintEvent() 함수를 호출해 Ctrl 키의 눌러짐 여부를
바로 화면에 고쳐 쓰도록 합니다.
[라인 35~38]
Ctrl 키의 떨어짐을 감지해 변수를 설정합니다.
[라인 40~46]
QWidget의 wheelEvent() 에 대한 오버라이딩이며 위젯에 마우스 휠 이벤트가 발생된 경우 호출되는 함수입니다.
이때 전달인자로 QWheelEvent 객체인 e가 전달되며, 이 클래스는 멤버함수로 마우스 휠 회전 변화량을 돌려주는 angleDelta(), pixelDelta() 두개의 함수를 갖습니다.
[Qt WheelEvent 설명 : 출처 Qt] |
다만 pixcelDelta() 함수는 High-resolution 을 지원하는 운영체제 (예 : macOS) 만 사용가능하다고 합니다.
따라서 저는 Windows를 사용하므로 예제에서 angleDelta() 를
사용하였습니다.
이 함수는 마우스 휠 각도 변화량이 120도 기준으로 리턴되므로 아래와 같이 적용하였습니다.
줌인, 아웃 = 120 / 120, 즉 변화량이 1도
스크롤 = 120 / 8, 즉 변화량이 15도
물론 이 값은 편리한대로 값을 조절해 사용하면 됩니다.
예) 120 / 12 = 변화량 10도
Qt 의 문서에 따르면 대부분의 경우 마우스 휠 스크롤은 15도가 기준이라고 합니다.
모든 마우스가 수직(Y), 수평(X) 휠 스크롤이 다 지원되지는 않으며, 제가
사용하는 마우스는 수평스크롤이 지원되는 모델이라 X값이 변하는 모습이 확인
가능합니다.
[라인 48~52]
코드가 시작되는 메인함수이며, QApplication 객체와 QWidget에서 상속받은 Form Class의 객체를 생성해 앱을 실행합니다.
이상으로 모든 설명을 마칩니다.
앱을 실행하고 마우스 휠을 조작하면 화면에 변화량이 표시됩니다.
감사합니다.
댓글
댓글 쓰기