2013-04-17 49 views
1

我創建了一個QLineEdit並附加了一個自定義的QValidator。我試圖給我的QValidator添加一個fixup()函數。當我在QLineEdit中輸入一些文本時,它會調用validate(),然後它會調用fixup(),最後再次調用validate(),但仍然與修復前的文本類似。我做錯了什麼?爲什麼QLineEdit沒有通過修正更新?QValidator.fixup()如何在PySide中工作?

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」 +回車):

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

看看'void QValidator :: fixup(QString&input)const'。 'input'是一個引用,'QString'是可變的。所以你應該在'fixup'中改變'text',而不是給它分配一個新的字符串。 – nymk

+1

在PySide中,QString是python字符串,函數參數是不可變的。 –

回答

0

我認爲默認實現QValidator在PySide並不好,其原因如下:

  1. validate()方法在輸入或刪除字符(即使在輸入完成之前)時被調用。這可能會使編輯字段變得不可能,因爲對目標字符串的所有編輯都是無效的並被拒絕。
  2. fixup()方法壞了,它的返回值被扔掉了。

但有一個解決方法。傳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) 
+0

我認爲這是不準確的。 'validate()'返回*三個可能的狀態之一:'valid','invalid'和'intermediate'。後者確保像你提到的情況不會發生。從文檔(http://srinikom.github.io/pyside-docs/PySide/QtGui/QValidator.html):「在可接受的字符串輸入過程中,任何可信的中間狀態的字符串都是」Intermediate「。 – neuronet

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)