13

Certain widgets will allow me to do:

self.widget.clicked.connect(on_click)

but doing:

self.widget.keyPressEvent.connect(on_key)

will fail saying that the object has no attribute 'connect'.

I know that sub-classing the widget and re-implementing the keyPressEvent method will allow me to respond to the event. But how can I .connect() to the keyboard event thereafter, or otherwise said, from a user context?

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
jpcgt
  • 2,138
  • 2
  • 19
  • 34
  • Correct me if I'm wrong, but keyPressEvent is not a slot so it can't be connected. You have to handle it using any of the event handlers. – f.rodrigues Dec 15 '14 at 01:45

2 Answers2

18

Create a custom signal, and emit it from your reimplemented event handler:

class MyWidget(QtGui.QWidget):
    keyPressed = QtCore.pyqtSignal(int)

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

def on_key(key):
    # test for a specific key
    if key == QtCore.Qt.Key_Return:
        print('return key pressed')
    else:
        print('key pressed: %i' % key)

self.widget.keyPressed.connect(on_key)

(NB: calling the base-class implementation is required in order to keep the existing handling of events).

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
  • 1
    Do you not need to overide `__init__` and call the super's `__init__`? – wesanyer Jan 25 '16 at 20:23
  • 1
    @wesanyer. No. Python always automatically calls `__init__` on each base-class, regardless of whether it has been overidden or not. But of course, if you **do** override `__init__`, you will then have to explicitly call the base-class implementation as well (because it will no longer be called automatically). – ekhumoro Jan 25 '16 at 23:12
  • 1
    what is on_key in this context? – Szabolcs Dombi Jul 11 '16 at 09:03
  • @DombiSzabolcs. It's a slot that is called when the signal is emitted. In PyQt/PySide, a slot can be any python callable. – ekhumoro Jul 11 '16 at 14:11
5

The way I've done this in the past is (it is a work around), where this is in the sender and the receiver declares/connects to the signal.

def keyPressEvent(self, event):
    if type(event) == QtGui.QKeyEvent:
        if event.key() == QtCore.Qt.Key_Space:
            self.emit(QtCore.SIGNAL('MYSIGNAL'))
chris
  • 4,840
  • 5
  • 35
  • 66