Search code examples
pyqt5qlineedit

QLineEdit: show new text before processing textEdited signal


I have a QLineEdit and a slot that processes the textEdited signal.

I don't want to validate the text, just use it to filter a list of names (different widget) with the ones matching the text in the QLineEdit.

I have found that the text shown in the QLineEdit is only updated after the signal is processed, and the question is: can I make the new text show in the QLineEdit first and then process the signal?

Now I have:

1. let's say user presses 'A' key in the QLineEdit
2. textEdited signal is emitted (but QLineEdit is not visually updated yet)
3. signal is processed in my slot (filtering a QListWidget)
4. QLineEdit is updated, showing the effect of pressing the key 'A' 

If step 3 takes a long time there is too much delay between the key is pressed and it's shown in the QLineEdit, so I want:

1. let's say user presses 'A' key in the QLineEdit
2. textEdited signal is emitted (but QLineEdit is not updated yet)
3. signal is processed in my slot (filtering a QListWidget)
   i) update the QLineEdit object to reflect the pressed key 'A'
   ii) filter the QListWidget

How can I do that? I need something like a QLineEdit.refresh() method? As I said I don't need to validate de text, I just want to use it to filter the content of a QListWidget, so I want everything the user edit to be shown as fast as possible.

EDIT: I've found that QCoreApplication.processEvents() does the work, but it affects the process of the signal, and some pressed keys don't trigger the signal, although I don't understand why. It seems that if the user say edits the QLineEdit pressing two keys "too fast" then the call to processEvents() in my slot (while processing the first key) processes the second key, so the second key is not processed by my slot. Does it make sense?


Solution

  • Use a single-shot timer:

    self.timer = QtCore.QTimer()
    self.timer.setSingleShot(True)
    self.timer.setInterval(300)
    self.timer.timeout.connect(self.filterList)
    self.edit.textChanged.connect(lambda: self.timer.start())
    

    This will keeping re-starting the timer until there's a pause greater than the timer interval, at which point the timeout signal will be sent and the slot connected to it will be called.

    You may need to adjust the interval to suit the typing speed.