I am handling multiple key presses by subclassing QMainWindow
and overriding the keyPressEvent
and keyReleaseEvent
functions, and then updating a dictionary if the key is down or not...
def keyPressEvent(self,event):
self.pressedKeys[event.key()] = True
def keyReleaseEvent(self,event):
self.pressedKeys[event.key()] = False
... and the pressedKeysArray
being:
pressedKeys = {Qt.Key_Left: False,
Qt.Key_Right: False,
Qt.Key_Down: False,
Qt.Key_Up: False}
However, I would like to be able to catch a double right arrow click, say within 100 or 200 milliseconds of each other. I would expand the pressedKeys
dictionary to include double clicked keys that can be set to True
or False
, but I don't know how to know if the key has been pressed twice in quick succession.
Here is my code so far:
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
class MainWindow(QMainWindow):
pressedKeys = {Qt.Key_Left: False,
Qt.Key_Right: False,
Qt.Key_Down: False,
Qt.Key_Up: False}
def __init__(self,parent=None,*args,**kwargs):
QMainWindow.__init__(self,parent,*args,**kwargs)
self.parent = parent
self.timer = QTimer()
self.timer.timeout.connect(self.keyAction)
self.timer.start(50)
self.show()
def keyPressEvent(self,event):
self.pressedKeys[event.key()] = True
def keyReleaseEvent(self,event):
self.pressedKeys[event.key()] = False
def keyAction(self):
if self.pressedKeys[Qt.Key_Left] and self.pressedKeys[Qt.Key_Down]: print("rolling left")
elif self.pressedKeys[Qt.Key_Right] and self.pressedKeys[Qt.Key_Down]: print("rolling right")
elif self.pressedKeys[Qt.Key_Left]: print("running left")
elif self.pressedKeys[Qt.Key_Right]: print("running right")
elif self.pressedKeys[Qt.Key_Down]: print("crouching") #return here to block effect of 'up' key being pressed
if self.pressedKeys[Qt.Key_Up]: print("jumping")
def exceptHook(exectype,value,traceback):
sys.__excepthook__(exectype,value,traceback)
if __name__ == "__main__":
sys.excepthook = exceptHook
app = QApplication(sys.argv)
mainWindow = MainWindow()
app.quit()
A possible solution is to keep a property last_pressed
to keep track of the most recent pressed key. Instead of using the timer to call keyAction
, just call keyAction
from the key press and release events. Now in the keyPressEvent
if the timer isActive
and last_pressed == event.key()
, you know it was a "double" key press. Otherwise, assign the last pressed key and start the timer. If the timer reaches timeout, reset last_pressed
.
class MainWindow(QMainWindow):
pressedKeys = {Qt.Key_Left: False, Qt.Key_Right: False,
Qt.Key_Down: False, Qt.Key_Up: False}
def __init__(self,parent=None,*args,**kwargs):
QMainWindow.__init__(self,parent,*args,**kwargs)
self.parent = parent
self.last_pressed = None
self.timer = QTimer()
self.timer.setSingleShot(True)
self.timer.timeout.connect(self.clear_pressed)
self.show()
def clear_pressed(self):
self.last_pressed = None
def keyPressEvent(self,event):
self.pressedKeys[event.key()] = True
if self.timer.isActive():
if self.last_pressed == event.key():
print('Double')
self.timer.stop()
else:
self.timer.start(200)
self.last_pressed = event.key()
self.keyAction()
def keyReleaseEvent(self,event):
self.pressedKeys[event.key()] = False
self.keyAction()