2

I’m trying to make a Lineedit that only accepts numbers from 1 to 12. But even using setValidator, the code can't limit the numbers. This is the function that has the LineEdit .(lineEdit should not accept numbers that are not between 1-12)

using Pyqt5 version 5.15.2 The OS is "Windows 7"

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *

class Ui_mainWindow(QMainWindow):
    def setupUi(self, mainWindow):
        mainWindow.setObjectName("mainWindow")
        mainWindow.resize(562, 605)
        self.centralwidget = QtWidgets.QWidget(mainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
        self.lineEdit.setGeometry(QtCore.QRect(176, 91, 101, 31))
        self.lineEdit.setValidator(QtGui.QIntValidator(1, 12, self))
        self.labelOutput = QtWidgets.QLabel(self.centralwidget)
        self.labelOutput.setGeometry(QtCore.QRect(176, 122, 101, 16))
        self.listWidget = QtWidgets.QListWidget(self.centralwidget)
        self.listWidget.setGeometry(QtCore.QRect(10, 182, 541, 351))
        self.btnEnviar = QtWidgets.QPushButton(self.centralwidget)
        self.btnEnviar.setGeometry(QtCore.QRect(500, 149, 51, 31))
        self.btnEnviar.clicked.connect(self.print)
        mainWindow.setCentralWidget(self.centralwidget)
        QtCore.QMetaObject.connectSlotsByName(mainWindow)

        _translate = QtCore.QCoreApplication.translate
        mainWindow.setWindowTitle(_translate("mainWindow", "title"))
        self.lineEdit.setText(_translate("mainWindow", "01"))
        self.btnEnviar.setText(_translate("mainWindow", "Send"))
        self.labelOutput.setText(_translate("mainWindow", "Output Number:"))
        mainWindow.show()
        
    def print(self):       
        self.listWidget.addItem(self.lineEdit.text())
        comando = 'MS01INVE'+ self.lineEdit.text()  + '\r'
        self.listWidget.addItem(comando)

app = QApplication([])
mainWindow = QMainWindow()
ui = Ui_mainWindow()
ui.setupUi(mainWindow)
app.exec_()


  • 2
    Please explain what you mean by "does not work", and provide an actual [mre]. – musicamante Dec 21 '21 at 19:31
  • The code you provided should conceptually work, so the problem must be somewhere else, and that's why you must provide a MRE: we must be able to copy, paste and run your code (possibly without any substantial modification) and be able to reproduce your issue. Right now your code not only does not reproduce anything (anything happens, as there's just a class declaration), but it can also raise a TypeError exception and make the program crash. – musicamante Dec 21 '21 at 21:03
  • Wait... Are you trying to type *multiple numbers* in that range, and at the same time, like "1 10 8 5 11"? – musicamante Dec 21 '21 at 21:10
  • i trying to type numbers between 1 to 12, the code must accept only the number in array [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] – Gustavo mota Dec 22 '21 at 16:06
  • The code above does exactly that. If I type 3, the input is accepted, if I try to type it again, there is no change. Are you able to write numbers bigger than 12? If that's the case, then provide a MRE as requested. – musicamante Dec 22 '21 at 16:10
  • Yes in can write a number bigger tha 12. I sent a new edition with a code that compiles (my mistake, I forgot to send this information) – Gustavo mota Dec 22 '21 at 17:05
  • The code you provide does not accept writing numbers higher than 12. What numbers are you able to type? Are you using some special peripheral to input text? What OS and PyQt version are you using? – musicamante Dec 22 '21 at 17:16
  • I using Windows 7 OS and PyQt5, i use the number 99 and works :( – Gustavo mota Dec 22 '21 at 17:18
  • We need the *specific* version, not just the major one. `from PyQt5 import QtCore; print(QtCore.QT_VERSION_STR)`. Also, please be more specific than "I use the number 99": we need the *exact* procerure. – musicamante Dec 22 '21 at 17:20
  • the version is 5.15.2, i typed the number 99 on the lineEdit and clicked on the send pushbutton. The listwidget printed the number 99. Besides the lineedit allowed me to type the number 99. – Gustavo mota Dec 22 '21 at 17:39
  • I voted to reopen this question, as, after further research, it seems that the shown behavior has indeed changed in the last versions of Qt: see [QTBUG-82915](https://bugreports.qt.io/browse/QTBUG-82915). As the documentation reports, QIntValidator *does* allow values out of range, otherwise in certain cases it would make editing difficult or impossible. While not optimal, this is now the "accepted" behavior. There are some possible solutions for this, and I voted to reopen to provide them. Note that you could always use [QSpinBox](https://doc.qt.io/qt-5/qspinbox.html). – musicamante Dec 22 '21 at 18:49

2 Answers2

2

According to QTBUG-82915, the previous behavior has changed. While the new behavior might seem unexpected, it is consistent with the documentation:

Notice that the value 999 returns Intermediate. Values consisting of a number of digits equal to or less than the max value are considered intermediate. This is intended because the digit that prevents a number from being in range is not necessarily the last digit typed. This also means that an intermediate number can have leading zeros.

Providing all possible exception of range restricted values is almost impossible, especially if the purpose is good performance. For instance, in your case, typing 9 results in an Intermediate value, but that doesn't prevent the function to try to add the line edit value.

While it's understandable that a validator should prevent invalid values to be typed, conceptually speaking the validator should only notify the control interface (the QLineEdit) that the input value is not valid, and it should be the interface's responsibility to deal with it.

There's no direct nor immediate solution for this, as it completely depends on use input and required behavior.

Since the main purpose is to use proper data input, a possible solution is to sanitize the value in the function that actually uses that input:

class MainWindow(QMainWindow, Ui_mainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.lineEdit.setValidator(QtGui.QIntValidator(1, 12, self))
        self.btnEnviar.clicked.connect(self.printData)

    def printData(self):
        value = self.lineEdit.text()
        validator = self.lineEdit.validator()
        if not value.isdigit():
            self.lineEdit.setText(str(validator.bottom()))
            return
        else:
            intValue = int(value)
            correctValue = max(validator.bottom(), min(intValue, validator.top()))
            if correctValue != intValue:
                value = str(correctValue)
                self.lineEdit.setText(value)
        self.listWidget.addItem(value)
        comando = 'MS01INVE'+ value + '\r'
        self.listWidget.addItem(comando)

Note: I had to change your original code and use an actual QWidget subclass (QMainWindow) with multiple inheritance. That's because the pyuic generated file you're using has also been modified, which is considered a bad practice. Please follow the official guidelines about using Designer in order to understand how to properly use those files.

musicamante
  • 41,230
  • 6
  • 33
  • 58
-3

Just put set maxlength like.

self.entry = QLineEdit(self)
self.entry.setMaxLength(10) # in this example the limit is 10 characters.
eyllanesc
  • 235,170
  • 19
  • 170
  • 241