I have been struggling mightily trying to grasp the implementation ins and out of validators, but I’m just not getting it.
I’m trying to start with something simple, but I’m stuck at way too early a phase.
For practice, I lifted the code below out of the wxPython in Action book. It’s code listing 9.15 starting on page 289. I modified it slightly to make it work from a panel instead of a dialog.
As posted, it does what it’s advertised to do. What I want it to do is to not just block certain inputs, but to actually change the input, for instance be able to append a ‘/’ character into the field at certain points. I was hoping I could somehow change the character being passed into the field in the OnChar() method, but nothing I’ve tried so far has had an effect.
I’d be grateful if someone can gently point me in the right direction – gently, because I’m feeling like something much less than a genius at the moment.
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.
“”"
class Frame(wx.Frame):
“”"The frame will house all the individual panels in the application. Only one panel or window will
be displayed at a time. It will also hold all the default values for the display."""
def init(self, title):
viewsize = (840, 650)
self.appcolor = “white”
wx.Frame.init(self, None, title=title, pos=(0,0), size=viewsize)
self.current_panel = MyPanel(self)
class CharValidator(wx.PyValidator):
def init(self, flag):
wx.PyValidator.init(self)
self.flag = flag
self.numchars = 0
self.Bind(wx.EVT_CHAR, self.OnChar) #<–Binding the character event
def Clone(self):
“”"
Note that every validator must implement the Clone() method.
“”"
return CharValidator(self.flag)
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:
return
evt.Skip()
class MyPanel(wx.Panel):
‘’‘Provides example fields’’’
def init(self, parent):
wx.Panel.init(self, parent)
self.SetBackgroundColour(parent.appcolor)
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:”)
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”)) # <–Binding the validator
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)
sizer.Add(fgs, 0, wx.EXPAND|wx.ALL, 5)
btns = wx.StdDialogButtonSizer()
btns.AddButton(okay)
btns.AddButton(cancel)
btns.Realize()
sizer.Add(btns, 0, wx.EXPAND|wx.ALL, 5)
self.SetSizer(sizer)
sizer.Fit(self)
app = wx.App()
top = Frame(“Validator Test”)
top.Show()
app.MainLoop()