QLineEdit::editingFinished called twice if press Enter key - actual bug?!
-
Tested under Linux (Qt 5.9.5 released with Ubuntu 18.04), and reported to me by users under Windows (I have reason to believe they are running a later version of Qt, like 5.11+).
- Create a
QLineEdit
. - Attach an
editingFinished()
slot. - Make the slot put up some kind of dialog.
- Press the Return key in the line edit to finish your editing.
You will get the dialog shown twice! :(
Instead of Return, use, say, Tab key to finish editing. You will only get the dialog shown once.
import sys from PyQt5 import QtWidgets def lineedit_editingFinished(): mbox = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Information, "editingFinished called", "editingFinished called") mbox.exec() if __name__ == '__main__': app = QtWidgets.QApplication(sys.argv) dlg = QtWidgets.QDialog() dlg.setFixedSize(400, 300) dlg.setLayout(QtWidgets.QVBoxLayout()) lineedit = QtWidgets.QLineEdit() lineedit.editingFinished.connect(lineedit_editingFinished) dlg.layout().addWidget(lineedit) extraLineeditJustSoYouCanTabOutOfFirstOne = QtWidgets.QLineEdit() dlg.layout().addWidget(extraLineeditJustSoYouCanTabOutOfFirstOne) dlg.show() sys.exit(app.exec_())
I don't think it's how/what you show as a dialog. But it needs something like that. It's something to do with the line edit losing focus to the up-popping dialog. But only when Return is pressed....
If you don't open a window/dialog in the slot but just, say, send a message to console, you do not get the twice. If you don't show a dialog but instead place a breakpoint, you will end up with the twice. Again, something to do with the debugger swapping up-front windows, just like a dialog, causing it.
Help/fix/workaround, please? :)
- Create a
-
The workaround is indeed:
if (!lineEditorWidget->isModified()) return; // Ignore second signal. lineEditorWidget->setModified(false); // Do something with the text.
i.e. you must clear the flag before doing something (which will invoke a dialog or similar) to prevent second, re-entrant call of
editingFinished
. -
Tested under Linux (Qt 5.9.5 released with Ubuntu 18.04), and reported to me by users under Windows (I have reason to believe they are running a later version of Qt, like 5.11+).
- Create a
QLineEdit
. - Attach an
editingFinished()
slot. - Make the slot put up some kind of dialog.
- Press the Return key in the line edit to finish your editing.
You will get the dialog shown twice! :(
Instead of Return, use, say, Tab key to finish editing. You will only get the dialog shown once.
import sys from PyQt5 import QtWidgets def lineedit_editingFinished(): mbox = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Information, "editingFinished called", "editingFinished called") mbox.exec() if __name__ == '__main__': app = QtWidgets.QApplication(sys.argv) dlg = QtWidgets.QDialog() dlg.setFixedSize(400, 300) dlg.setLayout(QtWidgets.QVBoxLayout()) lineedit = QtWidgets.QLineEdit() lineedit.editingFinished.connect(lineedit_editingFinished) dlg.layout().addWidget(lineedit) extraLineeditJustSoYouCanTabOutOfFirstOne = QtWidgets.QLineEdit() dlg.layout().addWidget(extraLineeditJustSoYouCanTabOutOfFirstOne) dlg.show() sys.exit(app.exec_())
I don't think it's how/what you show as a dialog. But it needs something like that. It's something to do with the line edit losing focus to the up-popping dialog. But only when Return is pressed....
If you don't open a window/dialog in the slot but just, say, send a message to console, you do not get the twice. If you don't show a dialog but instead place a breakpoint, you will end up with the twice. Again, something to do with the debugger swapping up-front windows, just like a dialog, causing it.
Help/fix/workaround, please? :)
@JonB said in QLineEdit::editingFinished called twice if press Enter key - actual bug?!:
Help/fix/workaround, please? :)
I've encountered the same thing today :-) SOunds like a bug to me, but I have not checked the bugtracker for it yet.
A workaround (depending on your use case) is to use
returnPressed()
signal instead. - Create a
-
@JonB said in QLineEdit::editingFinished called twice if press Enter key - actual bug?!:
Help/fix/workaround, please? :)
I've encountered the same thing today :-) SOunds like a bug to me, but I have not checked the bugtracker for it yet.
A workaround (depending on your use case) is to use
returnPressed()
signal instead.@sierdzio
Thanks for replying, useful to hear.A workaround (depending on your use case) is to use returnPressed() signal instead.
It's deliberately
editingFinished
because the user might tab out, or click elsewhere, or.... Funnily enough, in the current case the user may well have used aQCompleter
to populate the line edit and finish editing, so again he doesn't have to press Return. I just promised my stakeholders that these line edits would respond correctly to not pressing Return to finish editing!For now I've put in a "prevent-re-entrancy" flag on my
editingFinished
while the dialog is displayed to avoid bad behaviour, but I was hoping for a "nicer hack"? :) -
It might be QTBUG-40.
Looks like similar wording. And look who's been assigned to fix it! :) But it's been there since 2010 (the 40th bug ever found), surely it would have been fixed by now? :)
However, note my findings/example code --- in my case I am claiming this only happens if the Return key is pressed to cause the
QLineEdit::editingFinished
, I don't know if that's relevant or a special case? (Oh actually I think that's what the example in the 17 Jan '19 post says.) -
I've updated the link, it wasn't correctly accessible.
The issue has been fixed for Qt 5.14.
As for the assignment, look at the history ;-)
-
I've updated the link, it wasn't correctly accessible.
The issue has been fixed for Qt 5.14.
As for the assignment, look at the history ;-)
@sgaist
Thank you! I have a couple of questions/observations:-
I see this bug was actually first reported in 2005. Is this 14-years-to-fix a record for a Qt bug? :)
-
In the bug report link there is a workaround posted by a poster. I would like to implement this, as there is no chance of moving to a newer Qt version (I only use whatever Qt was released with the Linux version I use, so probably not until Ubuntu 20.04). It reads as follows:
I had to work around this bug once again today (Qt 5.6.1).
.
QLineEdit
has aisModified
interface. You can set this to true wheneditingFinished
is emitted the first time and ignore the signal if and when it is emitted the second time.
.
You can also use this to ignoreeditingFinished
if the text hasn't actually changed (i.e. theQLineEdit
simply lost focus).
.
This is my slot/lambda:connect( lineEditorWidget, &QLineEdit::editingFinished, this, [this, lineEditorWidget]() { if (!lineEditorWidget->isModified()) return; // Ignore second signal. lineEditorWidget->setModified(false); // Do something with the text. } );
Reading what he has written I am trying to confirm what his code really means to implement. Given the layout of his commented lines, do I presume this is intended to read as follows:
{ if (!lineEditorWidget->isModified()) return; // Ignore second signal. // Do something with the text. lineEditorWidget->setModified(false); }
Thus we only
setModified(false)
after we have finished our slot code? IfeditingFinished
is re-raised (by something) whilst we are inside the slot doing something with the text, we would execute our code again? As I typed this, I'm thinking he does genuinely meanlineEditorWidget->setModified(false); // Do something with the text.
which is different (you do the math): it ignores
editingFinished
being called a second time while inside the firsteditingFinished
, it's a "only do this once per modification, regardless of wheneditingFinished
is called"?He also says:
You can set this to true when
editingFinished
is emitted the first timebut the code does not do that, does he mean the Qt framework is doing this, not us? https://doc.qt.io/qt-5/qlineedit.html#modified-prop :
The modified flag is never read by
QLineEdit
; it has a default value of false and is changed to true whenever the user changes the line edit's contents. -
-
The workaround is indeed:
if (!lineEditorWidget->isModified()) return; // Ignore second signal. lineEditorWidget->setModified(false); // Do something with the text.
i.e. you must clear the flag before doing something (which will invoke a dialog or similar) to prevent second, re-entrant call of
editingFinished
.