You can also use a validator to validate data entered into the dialog as the user enters it, before the data is passed to the widget. This is very powerful, since it can prevent bad data from getting into your application. Figure 9.15 displays an example, the dialog text explains the idea.
This method of validating data is less automated than other mechanisms. You must explicitly bind the character events from the validator's widget to a function, as in the following:
The widget assumes that the event source belongs to the validator. Listing 9.15 displays this binding in action.
Listing 9.15 Validating on the fly import wx import string about_txt = \
The validator used in this example will validate the input on the fly instead of waiting until the okay button is pressed. The first field will not allow digits to be typed, the second will allow anything and the third will not allow alphabetic characters to be entered.
self.flag = flag self.Bind(wx.EVT_CHAR, self.OnChar) <— Binding the character event def Clone(self):
Note that every validator must implement the Clone() method.
def Validate(self, win): return True def TransferToWindow(self): return True def TransferFromWindow(self): return True def OnChar(self, evt):
key = chr(evt.GetKeyCode())
if self.flag == "no-alpha" and key in string.letters return if self.flag == "no-digit" and key in string.digits:
wx.Dialog._init_(self, None, -1, "Validators: behavior modification")
# Create the text controls about = wx.StaticText(self, -1, about_txt) name_l = wx.StaticText(self, -1, "Name:") email_l = wx.StaticText(self, -1, "Email:")
phone_l = wx.StaticText(self, -1, "Phone:") Binding the validator name_t = wx.TextCtrl(self, validator=CharValidator("no-digit")) <-email_t = wx.TextCtrl(self, validator=CharValidator("any")) phone_t = wx.TextCtrl(self, validator=CharValidator("no-alpha")) okay = wx.Button(self, wx.ID_OK) okay.SetDefault()
cancel = wx.Button(self, wx.ID_CANCEL) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(about, 0, wx.ALL, 5)
sizer.Add(wx.StaticLine(self), 0, wx.EXPAND|wx.ALL, 5)
fgs = wx.FlexGridSizer(3, 2, 5, 5) fgs.Add(name_l, 0, wx.ALIGN_RIGHT) fgs.Add(name_t, 0, wx.EXPAND) fgs.Add(email_l, 0, wx.ALIGN_RIGHT) fgs.Add(email_t, 0, wx.EXPAND) fgs.Add(phone_l, 0, wx.ALIGN_RIGHT) fgs.Add(phone_t, 0, wx.EXPAND) fgs.AddGrowableCol(1)
btns = wx.StdDialogButtonSizer() btns.AddButton(okay) btns.AddButton(cancel) btns.Realize()
app = wx.PySimpleApp()
Because the OnChar() method is in a validator, it gets called before the widget responds to the character event. The method allows the event to pass on to the widget by using Skip(). You must call Skip(), otherwise the validator interferes with normal event processing. The validator performs a test to see if the character is valid for the control. If the character is invalid, Skip() is not called, and event processing stops. If necessary, events other than wx.EVT_CHAR can also be bound and the validator handles those events before the widget does.
Validators are a powerful and flexible mechanism for handling data in your wxPython application. Using them properly helps make the development and maintenance of your application smoother.
Was this article helpful?