Implementing keyPressEvent in QWidget

32,495

Solution 1

You can do two ways and one is simply re implement keyPressevent with out any fancy work. Like this

from PyQt4 import QtCore, QtGui
import sys

class Example(QtGui.QWidget):
    def __init__(self):
        super(Example, self).__init__()
        self.setGeometry(300, 300, 250, 150)
        self.show()

    def keyPressEvent(self, event):
        if event.key() == QtCore.Qt.Key_Q:
            print "Killing"
            self.deleteLater()
        elif event.key() == QtCore.Qt.Key_Enter:
            self.proceed()
        event.accept()

    def proceed(self):
        print "Call Enter Key"

def main():
    app = QtGui.QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

Or as you tried with signals, in your case you where missing to implement this signal properly, here is updated version.

class Example(QtGui.QWidget):
    keyPressed = QtCore.pyqtSignal(QtCore.QEvent)
    def __init__(self):
        super(Example, self).__init__()
        self.setGeometry(300, 300, 250, 150)
        self.show()
        self.keyPressed.connect(self.on_key)

    def keyPressEvent(self, event):
        super(Example, self).keyPressEvent(event)
        self.keyPressed.emit(event) 

    def on_key(self, event):
        if event.key() == QtCore.Qt.Key_Enter and self.ui.continueButton.isEnabled():
            self.proceed()  # this is called whenever the continue button is pressed
        elif event.key() == QtCore.Qt.Key_Q:
            print "Killing"
            self.deleteLater()  # a test I implemented to see if pressing 'Q' would close the window

    def proceed(self):
        print "Call Enter Key"

def main():
    app = QtGui.QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

Solution 2

If you're looking at this in 2019, and If Achayan's method does not work for you then check a couple things :

1) Is the keyPressEvent overridden in a child of the main window or main widget? The child's function will override the methods on the parent (at least when using a QMainWindow with setCentralWidget). If this is the case, then the signal might not be emitted like you expect

2) Do you have a widget that handles key inputs differently than QWidget? For example, if the focus is in a QTextEdit object, then key inputs will not be sent to keyPressEvent. Shift focus to another widget

For example, observe the output of the following :

class myDialog(QtWidgets.QDialog):
    keyPressed = QtCore.pyqtSignal(QtCore.QEvent)

    def __init__(self, parent=None):
        super(myDialog, self).__init__(parent)
        self.keyPressed.connect(self.on_key)

        leftGroupBox = QtWidgets.QGroupBox('A Group Label')
        text = QtWidgets.QTextEdit('Enter some text')
        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(text)
        leftGroupBox.setLayout(layout)

        rightGroupBox = QtWidgets.QGroupBox('Label Options')
        label1 = QtWidgets.QCheckBox('ahu')
        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(label1)
        rightGroupBox.setLayout(layout)

        # Create the main layout
        mainLayout = QtWidgets.QGridLayout()
        mainLayout.addWidget(leftGroupBox)
        mainLayout.addWidget(rightGroupBox)
        self.setLayout(mainLayout)

    def keyPressEvent(self, event):
        # keyPressEvent defined in child
        print('pressed from myDialog: ', event.key())
#        self.keyPressed.emit(event) # Emit is hidden in child

    def on_key(self, event):
        print('event received @ myDialog')
        if event.key() == QtCore.Qt.Key_0:
            print(0)

class MainWindow(QtWidgets.QMainWindow):
    keyPressed = QtCore.pyqtSignal(QtCore.QEvent)

    def __init__(self):
        super(MainWindow, self).__init__()
        self.keyPressed.connect(self.on_key)
        self.setCentralWidget(myDialog())
        self.show()

    def keyPressEvent(self, event):
        super(MainWindow, self).keyPressEvent(event)
        print('pressed from MainWindow: ', event.key())
        self.keyPressed.emit(event)


    def on_key(self, event):
        print('event received @ MainWindow')
        if event.key() == QtCore.Qt.Key_0:
            print(0)

if __name__ == '__main__':
    ex = MainWindow()
Output @ console : (no event is received @myDialog OR MainWindow)
pressed from myDialog:  48

Solution 3

For Achayan's answer, I succeeded with the code. It may be the enter key and the return key. Try Key_Enter and Key_Return. They are different on my keyboard.

Share:
32,495
Peter Wang
Author by

Peter Wang

Python

Updated on November 25, 2020

Comments

  • Peter Wang
    Peter Wang over 3 years

    I have a QDialog window that has a continue button. The continue button is the default button because whenever I press the enter key, the continue button is pressed. I discovered something strange: when I press the enter key three times, the continue button presses three times. However, when I press it a fourth time, the whole window closes. I have a cancel button right below the continue button that closes the window, but I don't make the cancel button the default button or anything.

    I wanted to override the keyPressEvent so that whenever I'm in the window, the enter button will always be connected to the continue button.

    This is what I have right now:

    class ManualBalanceUI(QtGui.QWidget):
        keyPressed = QtCore.pyqtSignal()
    
        def __init__(self, cls):
            super(QtGui.QWidget, self).__init__()
            self.window = QtGui.QDialog(None, QtCore.Qt.WindowSystemMenuHint)
            self.ui = uic.loadUi('ManualBalanceUI.ui', self.window)
            self.keyPressed.connect(self.on_key)
    
        def keyPressEvent(self, event):
            super(ManualBalanceUI, self).keyPressEvent(event)
            self.keyPressed.emit(event) 
    
        def on_key(self, event):
            if event.key() == QtCore.Qt.Key_Enter and self.ui.continueButton.isEnabled():
                self.proceed()  # this is called whenever the continue button is pressed
            elif event.key() == QtCore.Qt.Key_Q:
                self.window.close()  # a test I implemented to see if pressing 'Q' would close the window
         def proceed(self):
             ...
         ...
    

    However, this doesn't seem to be doing anything right now. Pressing 'Q' doesn't close the window, and I can't really tell if the 'enter' key is working or not.

    I looked at this question beforehand: PyQt Connect to KeyPressEvent

    I also reviewed all the documentation on SourceForge. Any help would be greatly appreciated!

  • Peter Wang
    Peter Wang almost 8 years
    Thanks for the answer! I tried both ways and unfortunately they both aren't working for me. I'll keep playing around with it and I'll comment if something works
  • Achayan
    Achayan almost 8 years
    That should work, that's the possible minimal example I can provide.. good luck :)