我正在与wxPython's validators合作。我有一个文本字段,我只想接受数字,并且是必需的(不是留空。)一个快速的方法是简单地创建一个验证器类来完成这两件事,但是,我想做使用decorator pattern,并使用两个独立的,有凝聚力的验证器。这样我可以拥有可重用的验证器类,我可以在整个应用程序中混合和匹配。
例如,我希望能够分配这样的验证器:
requiredAndDigitsOnly = DigitValidator(RequiredValidator(CustomValidator()))
textField = wx.TextCtrl(sbSizer.GetStaticBox(), wx.ID_ANY,\
wx.EmptyString, wx.DefaultPosition, wx.DefaultSize,\
validator=requiredAndDigitsOnly)
我遇到了这个问题:当我尝试使用多个装饰器时(请参阅下面的代码),对self.GetWindow()
的调用会返回None
,所以验证停止,因为它无法获取正在验证的窗口的句柄。必须是因为toBeValidated
没有指向正确的窗口。 如何在wx.PyValidator中使用嵌套验证器?
这有效:RequiredValidator(CustomValidator())
但不是:DigitValidator(RequiredValidator(CustomValidator()))
Custom Validator
是wx.PyValidator
的子类:
import wx
class CustomValidator(wx.PyValidator):
'''
This is a basic validator that inherits from
PyValidator.
'''
def __init__(self):
super(CustomValidator, self).__init__()
def Clone(self):
# Every validator must implement a Clone method.
return CustomValidator()
def Validate(self, win):
return True
def TransferToWindow(self):
return True
def TransferFromWindow(self):
return True
RequiredValidator
和DigitValidator
是基础装饰器类的子类。以下是RequiredValidator
的外观(DigitValidator
几乎相同,除了处理验证方式不同):
class RequiredValidator(ValidatorDecorator):
def __init__(self, toBeDecorated):
super(RequiredValidator, self).__init__(toBeDecorated)
# Now add customization to the validator.
self.Bind(wx.EVT_SET_FOCUS, self.onClick)
def Clone(self):
# Every validator must implement a Clone method.
return self.__class__(self.toBeDecorated)
def Validate(self, win):
textControl = self.GetWindow()
value = textControl.GetValue()
if not len(value):
textControl.SetBackgroundColour('#FFFAC5')
return False
return super(RequiredValidator, self).Validate(win)
def onClick(self, event):
# ...
最后,基础装饰器类可能如下所示:
class ValidatorDecorator(wx.PyValidator):
'''
Abstract decorator class
'''
def __init__(self, toBeDecorated):
self.toBeDecorated = toBeDecorated
super(ValidatorDecorator, self).__init__()
def Clone(self):
# Every validator must implement a Clone method.
return self.toBeDecorated.Clone()
def Validate(self, win):
# Delegate this.
return self.toBeDecorated.Validate(win)
def GetWindow(self):
return super(self.__class__, self).GetWindow()
def TransferToWindow(self):
# Delegate this.
return self.toBeDecorated.TransferToWindow()
def TransferFromWindow(self):
# Delegate this.
return self.toBeDecorated.TransferFromWindow()