PySide6:如何用QIntValidator验证并拒绝QLineEdit的中间输入?
QLineEdit校验非Acceptable状态不生效的解决方法
问题还原
用QIntValidator(2, 100)给QLineEdit设置输入规则:
- 数字在2-100区间返回
QValidator.Acceptable - 数字超出范围返回
QValidator.Intermediate(输入可保留) - 输入字母返回
QValidator.Invalid(无法输入字母)
绑定editingFinished信号到somefunc,尝试三种方式拒绝非Acceptable状态输入,但仅Acceptable状态时代码生效,非Acceptable状态完全没反应:
第一种尝试代码:
if self.ui.StepsAmountLineEdit.hasAcceptableInput: print('SHIIIIIIIIET') else: self.ui.StepsAmountLineEdit.setText('42')
第二种尝试代码:
def somefunc(self): if self.ui.StepsAmountLineEdit.hasAcceptableInput: print('SHIIIIIIIIET') elif not self.ui.StepsAmountLineEdit.hasAcceptableInput: self.ui.StepsAmountLineEdit.setText('42')
第三种尝试代码:
def somefunc(self): value = self.ui.StepsAmountLineEdit.text() if self.validator.validate(value, 0)[0] == QValidator.Acceptable: self.ui.StepsAmountLineEdit.setText('42') print('SHIIIIIIIIET') elif self.validator.validate(value, 0)[0] == QValidator.Intermediate or self.validator.validate(value, 0)[0] == QValidator.Invalid: self.ui.StepsAmountLineEdit.setText('42') print('WOW')
核心原因
QLineEdit的editingFinished信号触发条件很严格:
- 仅当输入处于
Acceptable状态时,一定会触发 - 输入为
Intermediate状态时,只有用户主动按回车或让输入框失去焦点才可能触发 - 输入为
Invalid状态(比如输入字母)时,完全不会触发editingFinished信号,导致你的somefunc根本没机会执行。
解决方案
方案1:改用textChanged信号实时校验
放弃editingFinished,用textChanged监听每一次输入变化,不管什么状态都能捕获:
# 绑定信号 self.ui.StepsAmountLineEdit.textChanged.connect(self.validate_input) def validate_input(self, text): validator = self.ui.StepsAmountLineEdit.validator() state = validator.validate(text, 0)[0] if state != QValidator.Acceptable: # 断开信号避免无限循环,重置后重新绑定 self.ui.StepsAmountLineEdit.textChanged.disconnect(self.validate_input) self.ui.StepsAmountLineEdit.setText('42') self.ui.StepsAmountLineEdit.textChanged.connect(self.validate_input) else: print('SHIIIIIIIIET')
方案2:自定义Validator重写fixup方法
如果坚持用editingFinished,可以自定义Validator,在编辑结束时自动修正非法输入:
from PyQt5.QtGui import QIntValidator class CustomIntValidator(QIntValidator): def __init__(self, bottom, top, parent=None): super().__init__(bottom, top, parent) def fixup(self, input_str): # 编辑结束时自动修正非合法输入为42 try: num = int(input_str) if not (self.bottom() <= num <= self.top()): return '42' except ValueError: return '42' return input_str # 替换原Validator self.validator = CustomIntValidator(2, 100) self.ui.StepsAmountLineEdit.setValidator(self.validator) # 绑定editingFinished self.ui.StepsAmountLineEdit.editingFinished.connect(self.somefunc) def somefunc(self): # 此时fixup已经处理完非法输入,直接执行逻辑 print('SHIIIIIIIIET')
方案3:重写QLineEdit的focusOutEvent
如果希望用户离开输入框时再校验,重写输入框的失去焦点事件:
from PyQt5.QtWidgets import QLineEdit from PyQt5.QtGui import QIntValidator class CustomLineEdit(QLineEdit): def __init__(self, parent=None): super().__init__(parent) self.validator = QIntValidator(2, 100) self.setValidator(self.validator) def focusOutEvent(self, event): # 失去焦点时校验输入状态 state = self.validator.validate(self.text(), 0)[0] if state != QValidator.Acceptable: self.setText('42') # 调用父类方法保证原有逻辑正常执行 super().focusOutEvent(event) # 在UI文件中替换默认QLineEdit为CustomLineEdit,或者代码中创建实例
内容的提问来源于stack exchange,提问作者Pun Pun
相关产品推荐
相关产品推荐

