How do I make QIntValidator() call editingFinished when empty?

742 views Asked by At

I have a Line Edit widget with a QIntValidator:

number_textbox = QLineEdit()
number_textbox.setText("0")
number_textbox.setValidator(QIntValidator())

In addition, I am storing the old value of the textbox in a dict:

old_val[uid_key] = 0

I would like to be able to, when the textbox is empty, replace the text in the textbox with the old value if the user clicks outside the box or presses enter:

number_textbox.editingFinished.connect(lambda: self.editing_finished_function(number_textbox, old_val[uid_key]))

def editing_finished_function(self, textbox, old_val):
    if textbox.text() == '':
        textbox.setText(old_val)
    else:
        old_val = textbox.text()

Unfortunately, the QIntValidator() seems to consider empty values as invalid, and never fires my function. Is there a way to do what I'm looking for here?

1

There are 1 answers

1
Art On BEST ANSWER

from 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.

And QIntValidator doesn't seem to consider empty string to be valid. So I suggest you create your own validator using QRegExpValidator

Below is the validator that accepts both numeric and empty string

regexp = QtCore.QRegExp('(^[0-9]+$|^$)')
validator = QtGui.QRegExpValidator(regexp)

Full example:

import sys
from PyQt5 import QtWidgets, QtGui, QtCore


class MainWidget(QtWidgets.QWidget):

    old_val = {'val': '0'}

    def __init__(self):
        super(MainWidget, self).__init__()

        self.setLayout(QtWidgets.QVBoxLayout())
        self.setFocusPolicy(QtCore.Qt.ClickFocus)

        regexp = QtCore.QRegExp('(^[0-9]+$|^$)')
        validator = QtGui.QRegExpValidator(regexp)

        number_textbox = QtWidgets.QLineEdit()
        number_textbox.setText(self.old_val['val'])
        number_textbox.setValidator(validator)
        number_textbox.editingFinished.connect(lambda: self.editing_finished_function(number_textbox))

        self.layout().addWidget(number_textbox)

    def editing_finished_function(self, textbox):
        print("FINISHED")
        if textbox.text() == '':
            textbox.setText(self.old_val['val'])

        else:
            self.old_val['val'] = textbox.text()


if __name__ == '__main__':

    app = QtWidgets.QApplication(sys.argv)

    widget = MainWidget()
    widget.show()

    sys.exit(app.exec_())