Search code examples
pythonqtpyqtkeypressqplaintextedit

Python: Get keystrokes from QPlainTextWidget created by Qt Designer


I need to read the keystrokes typed into a QPlainTextWidget from a form created by Qt Designer.

I know that I can read the entire resulting text with QPlainTextWidget.toPlainText(), but I need to read the letters individually as they're typed. (I'm writing a file-renaming program for photographers and would like to display to the user the new filename that results from their typing into the text box. I use the their entry as a base name for the filename.)

I tried connecting a subroutine to the text box with self.txtFilename.keyPressDown.connect(self.DiplayNewFilename), but that produces an error because the keyPressDown is not a slot.

I've read online that subclassing can create a solution, but I don't know how do to that, or where to put the subclassing code into my overall code. My program is a single-form app that uses a GUI form I created in Qt Designer. I want to create a flexible solution that would let me add coding solution in my main Python file, rather than editing the GUI code generated by Qt Designer.

My current code only has one class (for the main window). Where would I put the new subclassing code -- inside this existing class, or as a new class? How would I call it?

I'm running Ubuntu 16.04, Python 3, and Qt 4. photoOrg_MainWindow.Ui_MainWindow in the code below is the form created by Qt Designer. txtFilename is the text widget whose keytrokes I want to capture.

Cheers, and thanks very much for your wisdom!

TL/DR: Is there a way to access text box key strokes from a text widget created in Qt Designer?

Here's the essence of my code so far:

class MainWindow(QtGui.QMainWindow, photoOrg_MainWindow.Ui_MainWindow):

    def __init__(self):
        super(self.__class__, self).__init__()
        self.setupUi(self)
        self.actionOpen_Files.triggered.connect(self.GetPhotoFileNames)
        self.txtFilename.keyPressDown.connect(self.DisplayNewFilename) #this doesn't work

    more irrelevant routines and connect bindings code here...

    def DisplayNewFilename(self):
        Code that processes the keystroke to display it as part of a sample new filename displayed in a QLabel

def main():
    app = QtGui.QApplication(sys.argv)
    form = MainWindow()
    form.show()                     
    app.exec_()                         

if __name__ == '__main__':              
    main() 

Solution

  • I think you are thinking about the problem too much :) .. an eventFilter can help you a lot. Here is a small example which can help a bit

    class Example(QtGui.QWidget):
        def __init__(self):
            super(Example, self).__init__()
            self.setGeometry(300, 300, 250, 150)
            vLayout = QtGui.QVBoxLayout(self)
            plainTextEdit = QtGui.QPlainTextEdit()
            self.newName = QtGui.QLineEdit()
            vLayout.addWidget(plainTextEdit)
            vLayout.addWidget(self.newName)
            plainTextEdit.installEventFilter(self)
            self.show()
    
        def eventFilter(self, sourceObj, event):
            if event.type() == QtCore.QEvent.KeyPress:
                if event.text() == "z":
                    self.newName.setText("do you mean zoo ?")
            return QtGui.QWidget.eventFilter(self, sourceObj, event)
    
    
    def main():
        app = QtGui.QApplication(sys.argv)
        ex = Example()
        sys.exit(app.exec_())
    
    if __name__ == '__main__':
        main()
    

    And keyPressDown is not a signal its event .. please read the docs for more hints