This post demonstrates how to use the QValidator
class to validate text input in PyQt4. Text validation can help the user to understand what information is required when entering data into a form. For example, preventing a user from entering letters into a text field that expects a number makes it clearer what is needed. In addition to this the colour of the text field can be changed to provide the user with a visual feedback, e.g. setting the text colour to red when an invalid input has been entered.
Basic use of QValidator with QLineEdit
To use a QValidator
, create an instance of it then apply it to a QLineEdit
using the setValidator
method. The example below uses a QDoubleValidator
to ensure that only text representing a valid double (i.e. a real number) can be input.
lineedit = QtGui.QLineEdit(self)
validator = QtGui.QDoubleValidator()
lineedit.setValidator(validator)
Multiple widgets can share a single QValidator
instance. If you have multiple QLineEdit
widgets that all need to accept a double you can point them all at the same validator.
Types of validator include QDoubleValidator
(for doubles), QIntValidator
(for integers) and QRegExpValidator
(for regular expressions, which covers almost everything else).
Changing the background colour to provide feedback
To give the user some visual feedback the background colour of a QLineEdit
can be changed to reflect the current validation state. The state must be either Acceptable, Intermediate or Invalid – see the QValidator documentation for a full description. The screenshots below show a QLineEdit
with a QDoubleValidator
in a intermediate state (yellow) and an acceptable state (green). The only way a QLineEdit can normally be in an invalid state is if the text is changed programatically using setText
or if the validator is set after the text has been entered.
The following method identifies the sender of the signal that called it, and validates it’s content using the assigned validator. The background colour of the widget is then set using the setStyleSheet
method.
def check_state(self, *args, **kwargs):
sender = self.sender()
validator = sender.validator()
state = validator.validate(sender.text(), 0)[0]
if state == QtGui.QValidator.Acceptable:
color = '#c4df9b' # green
elif state == QtGui.QValidator.Intermediate:
color = '#fff79a' # yellow
else:
color = '#f6989d' # red
sender.setStyleSheet('QLineEdit { background-color: %s }' % color)
To get this method to run every time the text changes, connect it to the QLineEdit
’s textChanged
signal. So that the inital state of the widget is validated the textChanged
signal is also emitted manually once.
lineedit.textChanged.connect(self.check_state)
lineedit.textChanged.emit(lineedit.text())
Evaluating fields before submitting a form
When the user submits a form a small function can be run to check that each input is valid. If there is an invalid field, instead of continuing with the process (resulting in an error later), the GUI can direct the user to the invalid field. The specifics of this will depend on the complexity of the form being validated, but it could be as simple as calling the setFocus()
method of a QLineEdit
to place the user’s cursor in the offending field.
Regular expressions
The QRegExpValidator
validator allows you to validate input using a regular expression. The Qt documentation for QRegExpValidator is quite clear, but it’s nice to have a Python example. The QLineEdit
in the following example will accept any integer between 0 and 255 inclusive.
lineedit = QtGui.QLineEdit(self)
regexp = QtCore.QRegExp('^([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])$')
validator = QtGui.QRegExpValidator(regexp)
lineedit.setValidator(validator)
Regular expressions are almost a language in themselves. The Python documentation includes an introduction to regular expressions.
Some people, when confronted with a problem, think “I know, I’ll use regular expressions.”
Now they have two problems.
– Jamie Zawinski, alt.religion.emacs