You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyQt6中重写QIntValidator的fixup()方法无效问题求助

PyQt6中QIntValidator子类fixup()方法不执行的解决办法

问题分析

你已成功将自定义IntValidator子类应用到QLineEdit派生类,但重写的fixup()方法未触发(如print语句无输出);原生QIntValidator的数字验证功能正常,但自定义修复逻辑失效。

核心原因

PyQt6中fixup()的触发有严格条件:

  1. 仅当输入文本验证状态为Invalid(如输入值超出1-255范围、空字符串需手动标记为Invalid),且控件失去焦点(或主动调用QLineEdit.fixup())时,fixup()才会被调用。
  2. 你的fixup()写法有误:Python字符串为不可变类型,直接赋值input = "123"无法修改原输入内容,需通过PyQt提供的字符串操作方法修改。

正确实现方案

1. 修正IntValidator的fixup()方法

需通过replace()方法修改传入的字符串对象,同时明确触发条件:

from PyQt6.QtGui import QIntValidator
from PyQt6.QtCore import QValidator

class IntValidator(QIntValidator):
    def validate(self, input_str, pos):
        # 调用父类验证逻辑
        state, input_str, pos = super().validate(input_str, pos)
        # 将空字符串标记为Invalid,触发fixup
        if not input_str.strip():
            return QValidator.State.Invalid, input_str, pos
        return state, input_str, pos

    def fixup(self, input_str):
        print("自定义fixup执行")
        # 将非法/空输入替换为最小值1
        input_str.replace(0, len(input_str), str(self.bottom()))

2. 验证触发逻辑

满足以下场景时,fixup()会自动执行:

  • 输入0(小于最小值1)后,点击窗口其他区域让控件失焦
  • 输入256(大于最大值255)后失焦
  • 输入空字符串后失焦(已通过重写validate()标记为Invalid)

3. 修正后的完整代码示例

IntValidator.py

from PyQt6.QtGui import QIntValidator
from PyQt6.QtCore import QValidator

class IntValidator(QIntValidator):
    def validate(self, input_str, pos):
        state, input_str, pos = super().validate(input_str, pos)
        if not input_str.strip():
            return QValidator.State.Invalid, input_str, pos
        return state, input_str, pos

    def fixup(self, input_str):
        print("自定义fixup执行")
        input_str.replace(0, len(input_str), str(self.bottom()))

StepsInput.py

from IntValidator import IntValidator
from LabeledInputInput import LabeledInputInput

class StepsInput(LabeledInputInput):
    def set_validator(self) -> None:
        validator = IntValidator(1, 255)
        self.setValidator(validator)

LabeledInputInput.py

from PyQt6.QtWidgets import QLineEdit
from PyQt6.QtCore import Qt, QRegularExpression
from PyQt6.QtGui import QRegularExpressionValidator
from PasteToMenu import PasteToMenu

class LabeledInputInput(QLineEdit):
    context_menu: PasteToMenu

    def __init__(self):
        super().__init__()
        self.context_menu = PasteToMenu()
        self.__set_appearance()
        self.set_validator()

    def contextMenuEvent(self, event):
        self.context_menu.exec(event.globalPos())

    def __set_appearance(self) -> None:
        self.setFixedSize(50, 20)
        self.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.setStyleSheet(self.__generate_style_sheet())

    def __generate_style_sheet(self) -> str:
        return '''        
            LabeledInputInput {
                background-color: #EEEEEE;
                border: 2px solid #FFD369;
                color: #393E46;
                font-size: 10pt;
                font-weight: bold;
            }
        ''' 

    def set_validator(self) -> None:
        pattern = '[0-9]+'
        regex = QRegularExpression(pattern)
        validator = QRegularExpressionValidator(regex)
        self.setValidator(validator)

关键注意事项

  • 触发时机:仅验证状态为Invalid时,控件失焦才会调用fixup();Acceptable或Intermediate状态不会触发。
  • 字符串修改:必须使用input_str.replace()修改内容,直接赋值无法改变原输入。
  • 参数命名:避免用input作为参数名,防止与Python内置input()函数冲突。

内容的提问来源于stack exchange,提问作者john

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 03:00:59