Использование QDoubleValidator для ограничения ввода QLineEdit и сброса значения до ближайшего приемлемого

Я хотел бы использовать QLineEdit для ввода пользователем значений. Я хочу ограничить ввод между диапазоном, поэтому я должен использовать QDoubleValidator. Я хотел бы, чтобы это работало так, что если они превышают допустимое значение, оно устанавливает для текста значение top(), а если они опускаются ниже, оно устанавливает его в значение bottom().

Я рассмотрел использование сигналов textChanged, returnPressed и inputRejected. Причина, по которой у меня возникают проблемы, заключается в том, что после того, как я установил валидатор с диапазоном, returnPressed не войдет в функцию check_validator, о которой они упоминают здесь. Затем я подумал, что, может быть, я смогу поймать его с отклоненным входным сигналом, но по какой-то причине это тоже не работает. Вот код:

class LineEdit(QLineEdit):
    def __init__(self, text, parent=None):
        super(LineEdit, self).__init__(parent)
        self.validator = QDouble Validator()
        self.setValidator(self.validator)
        self.text = text
        self.textChanged.connect(self.new_text)
        self.returnPressed(self.check_validator)

    def new_text(self, text):
        self.ntext = text

    def check validator:
        try:
            if float(self.ntext) > self.validator.top():
                self.text = str(self.validator.top()
            if float(self.ntext) < self.validator.bottom():
                self.text = str(self.validator.bottom()
            else:self.text = self.ntext
            self.setText(self.text)
         except:
            mssg = QMessageBox.about(self, "Error", "Input can only be a number")
            mssg.exec()
            self.setText(self.text)

     def valRange(self, x1, x2):
         self.validator.setRange(x1, x2)

Я также получаю сообщение об ошибке атрибута, говорящее, что объект «noneType» не имеет атрибута «exec», когда окно всплывает. Я думаю, что мне не хватает шага о том, как правильно закрыть это окно.


person Amanda.py    schedule 01.03.2021    source источник
comment
Есть ли конкретная причина, по которой вы не используете простой QDoubleSpinBox?   -  person musicamante    schedule 02.03.2021
comment
Я не знал об этом классе раньше, похоже, он мог бы сработать, но приведенное ниже решение сработало, поэтому я его оставлю. Спасибо за предложение!   -  person Amanda.py    schedule 02.03.2021
comment
Я предлагаю вам ознакомиться с классами виджетов. документации, он содержит полный список доступных виджетов, включая варианты базовых классов. Я бы также посоветовал вам всегда пытаться использовать объекты по их назначению, если только не требуются очень специфические и особые требования. QLineEdit предназначен для ввода строки (даже числового, например, IP-адреса), в то время как объекты, которые должны рассматриваться как фактические числа, всегда должны использовать подкласс QAbstractSpinBox, поскольку он предоставляет более подходящее управление.   -  person musicamante    schedule 02.03.2021


Ответы (1)


Вы можете переопределить keyPressEvent для перехвата возвратных нажатий, когда hasAcceptableInput имеет значение false. Также есть недостаток переопределения свойства text, теперь любые программные вызовы setText не будут обновлять текст QLineEdit. Нет причин делать это.

class LineEdit(QLineEdit):
    def __init__(self, *args, **kwargs):
        super(LineEdit, self).__init__(*args, **kwargs)
        self.validator = QDoubleValidator(0, 10, 4, notation=QDoubleValidator.StandardNotation)
        self.setValidator(self.validator)
        self.textChanged.connect(self.new_text)
        self.returnPressed.connect(self.check_validator)
        self.ntext = None

    def keyPressEvent(self, event):
        super().keyPressEvent(event)
        if event.key() == Qt.Key_Return and not self.hasAcceptableInput():
            self.check_validator()

    def new_text(self, text):
        if self.hasAcceptableInput():
            self.ntext = text

    def check_validator(self):
        try:
            if float(self.text()) > self.validator.top():
                self.setText(str(self.validator.top()))
            elif float(self.text()) < self.validator.bottom():
                self.setText(str(self.validator.bottom()))
        except:
            mssg = QMessageBox.about(self, "Error", "Input can only be a number")
            self.setText(self.ntext)
person alec    schedule 01.03.2021
comment
Потрясающе, спасибо. Единственное, если ввод недействителен, я бы хотел, чтобы он вернулся к ранее приемлемому значению. - person Amanda.py; 02.03.2021
comment
Также странно (но на самом деле это не проблема...), что вы не можете ввести более одного символа. Кроме того, спасибо за объяснение этого о setText. Я действительно задавался этим вопросом. теперь исходные значения, которые я ввел в их инициализацию, также действительно отображаются. - person Amanda.py; 02.03.2021
comment
Теперь я понимаю, почему у тебя было self.ntext. я отредактировал ответ - person alec; 02.03.2021
comment
В ответ я поставил диапазон 0-10, 4 десятичных предела, и стандартное обозначение на валидаторе, вы не можете ввести более одного символа?? - person alec; 02.03.2021
comment
Я просто имею в виду, что вы не можете печатать обычные буквы, но это не имеет значения, и понятно, почему вы не можете. - person Amanda.py; 02.03.2021