5

I'm writing Chat gui for client on Python using PyQt5. I have a QTextEdit, which the client can write messages in it. I wan't to know when the 'Enter' key is being pressed while the focus is on the QTextEdit.

I tried using installEventFilter function but it detects keys being pressed on all of the other widgets but the QTextEdit one. What can I do to fix that?

def initUI(self):
   # ...
    self.text_box = QtWidgets.QTextEdit(self)
    self.installEventFilter(self)
    # ...

def keyPressEvent(self, qKeyEvent):
    print(qKeyEvent.key())
    if qKeyEvent.key() == Qt.Key_Return:
        if self.text_box.hasFocus():
            print('Enter pressed')
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Daniel Segal
  • 87
  • 3
  • 9

3 Answers3

10

When you override keyPressEvent you are listening to the events of the window, instead install an eventFilter to the QTextEdit, not to the window as you have done in your code, and check if the object passed as an argument is the QTextEdit:

def initUI(self):
    # ...
    self.text_box = QtWidgets.QTextEdit(self)
    self.text_box.installEventFilter(self)
    # ...

def eventFilter(self, obj, event):
    if event.type() == QtCore.QEvent.KeyPress and obj is self.text_box:
        if event.key() == QtCore.Qt.Key_Return and self.text_box.hasFocus():
            print('Enter pressed')
    return super().eventFilter(obj, event)
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • 1
    Thanks, a lot. Can I ask another thing? How return the cursor in the QTextEdit back to the start of the QTextEdit (after hitting enter its going down one line), I made it so every time the client presses enter, it will delete the text in the text_box. but its still keeping the text cursor one line down. – Daniel Segal Aug 28 '19 at 19:48
  • @DanielSegal Create another question and provide a [MRE] so that a possible solution can indicate the possible error of your code and a solution. – eyllanesc Aug 28 '19 at 19:51
  • @DanielSegal I just posted an answer that fixes this – tbrodbeck Jan 11 '21 at 18:29
  • @Tillus Please read [ask] and [answer], in SO you cannot add more requirements to your post through a comment so I tell the OP to create a new post, if you answer it (as you have already done) then you are promoting such inappropriate actions. I will report your answer to be removed – eyllanesc Jan 11 '21 at 18:36
  • I read the question and I am pretty sure that I improved the answer. Most people with that use case do not want to have a new line when filtering enter input. So I really do not understand the "harm" here, maybe some more specifics on that would be helpful. – tbrodbeck Jan 11 '21 at 19:58
3

The answer from @eyllanesc is very good if you are determined to use QTextEdit.

If you can get away with QLineEdit and its limitations, you can use the returnPressed() signal. The biggest drawback for QLineEdit is you are limited to one line of text. And there is no word wrap. But the advantage is you don't have to mess with eventFilters or think too hard about how keyPress signals fall through all of the widgets in your app.

Here is a minimal example that copies from one QLineEdit to another:

import sys

from PyQt5.QtWidgets import * 


class PrintWindow(QMainWindow):

    def __init__(self):
        super().__init__()
        self.left=50
        self.top=50
        self.width=300
        self.height=300
        self.initUI()

    def initUI(self):

        self.setGeometry(self.left,self.top,self.width,self.height)

        self.line_edit1 = QLineEdit(self)
        self.line_edit1.move(50, 50)
        self.line_edit1.returnPressed.connect(self.on_line_edit1_returnPressed)

        self.line_edit2 = QLineEdit(self)
        self.line_edit2.move(50, 100)

        self.show()

    def on_line_edit1_returnPressed(self):
        self.line_edit2.setText(self.line_edit1.text())

if __name__ == '__main__':

    app = QApplication(sys.argv)
    window = PrintWindow()
    sys.exit(app.exec_())

In this example, I have manually connected to the signal in line 22 (self.line_edit1.returnPressed.connect). If you are using a ui file, this connection can be left out and your program will automatically call the on__returnPressed method.

bfris
  • 5,272
  • 1
  • 20
  • 37
1

When you override keyPressEvent you are listening to the events of the window, instead install an eventFilter to the QTextEdit, not to the window as you have done in your code, and check if the object passed as an argument is the QTextEdit:

def initUI(self):
    # ...
    self.text_box = QtWidgets.QTextEdit(self)
    self.text_box.installEventFilter(self)
    # ...

def eventFilter(self, obj, event):
    if event.type() == QtCore.QEvent.KeyPress and obj is self.text_box:
        if event.key() == QtCore.Qt.Key_Return and self.text_box.hasFocus():
            print('Enter pressed')
            return True
    return False

This is building upon the answer of @eyllanesc and the problem @Daniel Segal faced. Adding the correct return values as such to the eventFilter solves the problem.

tbrodbeck
  • 460
  • 1
  • 8
  • 16