SaltyCrane Blog — Notes on Javascript and web development

How to capture the Tab key press event with PyQt 4.3

Normally, pressing the TAB key changes focus among widgets. However, I would like to use the TAB key for other purposes (e.g. tab completion). To gain control of the TAB key press event, I need to subclass my widget and reimplement the QObject.event() event handler. I don't need to re-write the entire event handler. I only need to process TAB key press events. I will pass all other events to the default event handler. The example below subclasses the QLineEdit widget and reimplements the event() method. Pressing the TAB key inside this new widget prints out the text "tab pressed" inside a second QLineEdit box.

The Events and Event Filters Trolltech QT documentation has a good explanation of how this works. My example shows how to use Python and PyQt instead of C++.

import sys
from PyQt4.QtCore import * 
from PyQt4.QtGui import * 

#################################################################### 
def main(): 
    app = QApplication(sys.argv) 
    w = MyWindow() 
    w.show() 
    sys.exit(app.exec_()) 

####################################################################
class MyWindow(QWidget): 
    def __init__(self, *args): 
        QWidget.__init__(self, *args)

        # create objects
        self.la = QLabel("Press tab in this box:")
        self.le = MyLineEdit()
        self.la2 = QLabel("\nLook here:")
        self.le2 = QLineEdit()

        # layout
        layout = QVBoxLayout()
        layout.addWidget(self.la)
        layout.addWidget(self.le)
        layout.addWidget(self.la2)
        layout.addWidget(self.le2)
        self.setLayout(layout)

        # connections
        self.connect(self.le, SIGNAL("tabPressed"),
                     self.update)

    def update(self):
        newtext = str(self.le2.text()) + "tab pressed "
        self.le2.setText(newtext)

####################################################################
class MyLineEdit(QLineEdit):
    def __init__(self, *args):
        QLineEdit.__init__(self, *args)
        
    def event(self, event):
        if (event.type()==QEvent.KeyPress) and (event.key()==Qt.Key_Tab):
            self.emit(SIGNAL("tabPressed"))
            return True

        return QLineEdit.event(self, event)

####################################################################
if __name__ == "__main__": 
    main()

Comments


#1 mk18 commented on :

good example,thnx


#2 William commented on :

Thanks, I was trying to reimplement keyPressedEvent and it wasn't working, but this set me straight.


#3 BMG commented on :

Thank you very much for this very clear and useful example ! It saved me a lot of google-time !


#4 Amy commented on :

Thanx it's very helpfyl :)


#5 Anas Sami Al-Taji commented on :

Thanks for this nice & clear tips..%


#6 Mark commented on :

This is exactly what I need, except one thing- how would I implement this without using addWidget? I create my UI in QT Designer and when I attempt to assign this to an existing control it ignores it.

Is there an easy way to assign this to an existing qWidget?

Thanks for a great tutorial!


#7 Carlos commented on :

Awsome tutorial man, thanx a lot for it.

I've got an additional question, I have several QLineEdits in my app, and I need a special behaviour of these ones; for example (I have 5), the first four QLineEdits accept enter by validating its contents - if they have or not text-. If they have text, Enter will make the focus to go to the next qlineedit, but the last one will also validate text content and will call a method to be used.

Or, in my app I'm using a groupbox in which are five radiobuttons; according on which radiobutton is selected or checked a qlineedit will get the focus and this will have to accept enter by validating text content and calling a method to make a query in a data base.

How can I make such a thing? I will be very thankfull for your support.