为什么 editingFinished 信号在连接的插槽显示 QMessageBox 时产生两次?

Why does editingFinished signal generates two times when QMessageBox is being shown by connected slot?

from PySide2 import QtWidgets


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.lineEdit = QtWidgets.QLineEdit()
        self.lineEdit.setText("1")
        self.lineEdit.editingFinished.connect(self.check)
        self.lineEdit2 = QtWidgets.QLineEdit()
        vlay = QtWidgets.QVBoxLayout(self)
        vlay.addWidget(self.lineEdit)
        vlay.addWidget(self.lineEdit2)

    def check(self):
        if self.lineEdit.text() == "1":
            popup = QtWidgets.QMessageBox(self)
            popup.setWindowTitle("why")
            popup.show()
            print("test")


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

因此在此脚本中,如果您在编辑 "lineEdit" 时按 "Enter",则会调用两次 "check" 插槽。但是如果你点击 "lineEdit2",槽将只被调用一次,这是应该的。发生这种情况是因为 QMessageBox,但为什么呢?

如果勾选 the docs:

void QLineEdit::editingFinished()

This signal is emitted when the Return or Enter key is pressed or the line edit loses focus. Note that if there is a validator() or inputMask() set on the line edit and enter/return is pressed, the editingFinished() signal will only be emitted if the input follows the inputMask() and the validator() returns QValidator::Acceptable.

(强调我的)

在您的情况下,当您按下 Enter 时给出第一次打印,当 QLineEdit 失去焦点时给出第二次打印,因为 QMessageBox 获得它。


如果你想避免这种行为,你可以在 QMessageBox 显示之前阻止 QLineEdit 事件的发射,直到它显示之后:

<b>self.lineEdit.blockSignals(True)</b>
popup = QtWidgets.QMessageBox(self)
popup.setWindowTitle("why")
<b>QtCore.QTimer.singleShot(100, lambda: self.lineEdit.blockSignals(True))</b>
popup.show()
print("test")