Interaction between QLineEdit editingFinished signal and button press

461 Views Asked by At

I have a QLineEdit in a QDialog with a QButtonBox in the dialog. The QLineEdit's editingFinished signal is connected to a function. The function is called if the QLineEdit loses focus, as expected. When the focus is lost to pressing the Ok button is where I get confused. My signal handler is called, as expected, but the Ok button accepted() signal is not emitted. Why is this signal lost? In particular, if the dialog is exec()'ed, hitting the OK button when focus is on my QLineEdit does not end the dialog, it just invokes the editingFinished handler. My handler calls a QMessageBox, and this is what appears to be breaking the accepted signal. If I comment it out, then I get the expected behavior.

Is the accepted() signal from the QMessageBox interfering with the signal from the QButtonBox? If so, what's the right way to handle this?

edit - Run the code below. Click in the QLineEdit box, then click Ok. You will see a msg box. Click OK on the msg box and you're back in the dialog, with the Ok button having focus and indicating the "down" state. Checking the button with isDown() returns false, so it apparently doesn't transition to the down state until myHandler returns. Now comment out the msg_box.exec() line and repeat the steps above. Clicking the Ok button exits the dialog.

The behavior I'm seeking is for the Ok button action (accepted) to execute after the return from myHandler(). I know I can emit the accepted or rejected signal from myHandler, but that requires testing which button was pressed. I think I can tell that by checking focus, but I'm hoping there's a cleaner approach. And more generally, I'm curious what's happening to the signals a the pressed button is emitting but seem to be getting lost or gobbled up.

from PyQt5 import QtCore, QtGui, QtWidgets
import sys

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(640, 480)
        self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
        self.buttonBox.setGeometry(QtCore.QRect(10, 440, 621, 32))
        self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
        self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
        self.buttonBox.setObjectName("buttonBox")
        self.lineEdit = QtWidgets.QLineEdit(Dialog)
        self.lineEdit.setGeometry(QtCore.QRect(180, 180, 251, 31))
        self.lineEdit.setObjectName("lineEdit")

        self.retranslateUi(Dialog)
        self.buttonBox.accepted.connect(Dialog.accept)
        self.buttonBox.rejected.connect(Dialog.reject)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))

class MyDialog(QtWidgets.QDialog, Ui_Dialog):
  def __init__(self, parent= None):
    QtWidgets.QDialog.__init__(self)
    self.setupUi(self)
    self.lineEdit.editingFinished.connect(self.myHandler)

  def myHandler(self):
    print ("My handler called")
    msg_box = QtWidgets.QMessageBox()
    msg_box.setText("Your Message here")
    msg_box.exec()



if (__name__ == '__main__'):
  app = QtWidgets.QApplication(sys.argv)
  myapp = MyDialog()
  myapp.show()
  sys.exit(app.exec())
0

There are 0 best solutions below