QValidator.fixup()如何在PySide中运行?

时间:2013-04-17 18:54:08

标签: python pyside

我创建了一个QLineEdit并附加了一个自定义QValidator。我试图在我的QValidator中添加fixup()函数。当我在QLineEdit中输入一些文本时,它调用validate(),然后调用fixup(),最后再次调用validate(),但仍然使用类似于修复之前的文本。我做错了什么?为什么修正后没有更新QLineEdit?

mylineedit = QtGui.QLineEdit()
mylineedit.setValidator(MyValidator())

class MyValidator(QtGui.QRegExpValidator):
    def __init__(self, parent=None):
        rx = QtCore.QRegExp('\\d+ m')
        super().__init__(rx, parent)

    def validate(self, text, pos):
        r = super().validate(text, pos)
        print(r)
        return r

    def fixup(self, text):
        if len(text) == 0:
            text = '0 m'
        else:
            text = text.strip() + ' m'
        print(text)
        return text

输出类似于(如果我按下' 1' + Enter):

(PySide.QtGui.QValidator.State.Intermediate, '1', 1)
1 m
(PySide.QtGui.QValidator.State.Intermediate, '1', 1)

2 个答案:

答案 0 :(得分:1)

我认为PySide中 QValidator 的默认实现不好,原因如下:

  1. 即使在输入完成之前,只要输入或删除字符,就会调用validate()方法。这可能会使编辑字段变得不可能,因为对目标字符串的所有编辑都是无效的并且被拒绝。
  2. fixup()方法被破坏,它的返回值被丢弃。
  3. 但是有一个解决方法。将QLineEdit本身传递给验证器构造函数,然后您可以控制它何时被验证并根据需要修复它的值:

    class MyValidator(QValidator):
    
      def __init__(self, lineedit):
        super(MyValidator, self).__init__()
        self.lineedit = lineedit
    
      def validate(self, s, p):
        if self.lineedit.hasFocus(): #ignore validation while editing not complete
          return QValidator.Acceptable
        if s.startswith("http://"):
          return QValidator.Acceptable
        return QValidator.Invalid
    
      def fixup(self, s):
        self.lineedit.setText("http://" + s)
    

答案 1 :(得分:1)

根据MadeOfAirs的回答,提出了以下替换空白的方法。但是,它为每个小部件创建了一个新的验证器。

class QLineEditValidator(QValidator):

    @classmethod
    def connect(cls, line_edit, fixup=lambda s: s, validate=None, **kwargs):
        line_edit.setValidator(cls(line_edit, fixup=fixup, validate=validate, **kwargs))

    def __init__(self, line_edit, fixup=lambda s: s, validate=None, **kwargs):
        super().__init__(**kwargs)
        self.line_edit, self._fixup, self._validate = line_edit, fixup, \
            (lambda s, p: fixup(s) == s) if validate is None else validate

    def validate(self, s, p):
        if self.line_edit.hasFocus():
            return QValidator.Acceptable
        return QValidator.Acceptable if self._validate(s, p) else QValidator.Invalid

    def fixup(self, s):
        self.line_edit.setText(self._fixup(s))

text = QLineEdit()
QLineEditValidator.connect(text, fixup=lambda s: s.replace(' ', '_'))
QLineEditValidator.connect(text, fixup=lambda s: s.replace(' ', '_'), 
    validate=lambda s, p: not ' ' in s)
相关问题