Nested validation

Hello

I'm writing a simple app to take some details from users at login.
So far I have setup validation to ensure that the various text fields
are filled in and to collect the input from these fields.

However, in one case the text field should only contain some text if a
checkbox has been checked. In other words, the validator for this
text field only needs to run if the checkbox has been checked.
Clearly the validation can't take place immediately the checkbox is
clicked as then the user won't have any time to fill the text field.

I would be grateful for any suggestions as this is my first wxPython project.

Adam

Hello

I'm writing a simple app to take some details from users at login.
So far I have setup validation to ensure that the various text fields
are filled in and to collect the input from these fields.

However, in one case the text field should only contain some text if a
checkbox has been checked. In other words, the validator for this
text field only needs to run if the checkbox has been checked.
Clearly the validation can't take place immediately the checkbox is
clicked as then the user won't have any time to fill the text field.

I would be grateful for any suggestions as this is my first wxPython project.

Adam

If I were you, I would set the text control to disabled until the checkbox is checked. Then in the checked event handler, I would enable the text control. Text controls accept validators as part of their instantiation, so if you create it with one already linked, you won't need to add it later. I'm not even sure you can add one after it's been created. Anyway, the validator doesn't do anything until the user actually starts typing into the text control.

See the following for more on Validators:

http://wiki.wxpython.org/Validator%20for%20Object%20Attributes
http://wiki.wxpython.org/DataFormatters

There's also a Validator demo in the wxPython demo.

Mike

Hmm. I wrote a full series of validators to validate XML files, but
the base classes can be used to validate all sorts of string data.
I've been using a longer workaround, though. I call up a dialog for
user input, once the user clicks SAVE the dialog collects the data,
makes the XML Element, passes it to the validator, and then reports if
something is wrong.

I didn't even think to attach Validators to each field of the dialog
box, and I'm not sure I have to. Because my Validators accept
strings, why not have this:

    email =self.Email.GetValue()
    try: emailCheck(email)
    except EmailCheckError: wx.MessageBox("Bad email address you
yutz","Oops"); evt.Veto()

Ok, ignoring the facts that wx.EVT_BUTTON doesn't seem to have a Veto method...

But what does a pyVaildatorObject give me over this?

Josh

···

On Fri, May 30, 2008 at 8:19 AM, Mike Driscoll <mdriscoll@co.marshall.ia.us> wrote:

Hello

I'm writing a simple app to take some details from users at login.
So far I have setup validation to ensure that the various text fields
are filled in and to collect the input from these fields.

However, in one case the text field should only contain some text if a
checkbox has been checked. In other words, the validator for this
text field only needs to run if the checkbox has been checked.
Clearly the validation can't take place immediately the checkbox is
clicked as then the user won't have any time to fill the text field.

I would be grateful for any suggestions as this is my first wxPython
project.

Adam

If I were you, I would set the text control to disabled until the checkbox
is checked. Then in the checked event handler, I would enable the text
control. Text controls accept validators as part of their instantiation, so
if you create it with one already linked, you won't need to add it later.
I'm not even sure you can add one after it's been created. Anyway, the
validator doesn't do anything until the user actually starts typing into the
text control.

See the following for more on Validators:

Validator for Object Attributes - wxPyWiki
DataFormatters - wxPyWiki

There's also a Validator demo in the wxPython demo.

Mike

_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

--
Josh English
Joshua.R.English@gmail.com

Mike Driscoll wrote:

Hello

I'm writing a simple app to take some details from users at login.
So far I have setup validation to ensure that the various text fields
are filled in and to collect the input from these fields.

However, in one case the text field should only contain some text if a
checkbox has been checked. In other words, the validator for this
text field only needs to run if the checkbox has been checked.
Clearly the validation can't take place immediately the checkbox is
clicked as then the user won't have any time to fill the text field.

I would be grateful for any suggestions as this is my first wxPython project.

Adam

If I were you, I would set the text control to disabled until the checkbox is checked. Then in the checked event handler, I would enable the text control. Text controls accept validators as part of their instantiation, so if you create it with one already linked, you won't need to add it later. I'm not even sure you can add one after it's been created. Anyway, the validator doesn't do anything until the user actually starts typing into the text control.

Thanks for the advice. I've tried to do that, but a validator is being called as soon as the text control is enabled. I've based my code on the wxPIA examples that came with my installation, in the Chapter-09 directory. Here's the relevant code:

class MyDialog(wx.Dialog):
    def __init__(self, data):
               wx.Dialog.__init__(self, None, wx.ID_ANY, 'Validation test', pos=(100, 100),
                          size=(1000, 700))

        text = wx.StaticText(self, -1, "User name and account details",
                             (20, 10))
        text.SetFont(wx.Font(14, wx.SWISS, wx.NORMAL, wx.BOLD))

        self.text2 = wx.TextCtrl(self, -1, "Test text", size=(175, -1),
                                 pos=(20, 150), validator=DataXferValidator(data, "account"))

        self.acctick_c = wx.CheckBox(self, -1, "Tick if you don't know your account details",
                                (20, 330))
        self.acctick_l = wx.StaticText(self, -1, "If ticked, please enter your e-mail address:",
                                  pos=(20, 380))
        self.acctick_t = wx.TextCtrl(self, -1, "", size=(175, -1),
                                pos=(330, 380), validator=DataXferValidator(data, "email") )
        self.acctick_t.Disable()
        self.acctick_l.Disable()
        self.acctick_c.Bind(wx.EVT_CHECKBOX, self.ShowTextCtrl)

        self.okay = wx.Button(self, wx.ID_OK, pos=(500, 500))
        self.okay.SetDefault()

    def ShowTextCtrl(self, event):
        self.acctick_t.Enable()
        self.acctick_l.Enable()

At the moment the validation works as expected for the first text field. For the second text filed, which is disabled until the box is checked, the validation is called anyway, even though the user can't edit it.

Do I need to add another test in the validation code, to ensure the window has been enabled?

Adam

···

See the following for more on Validators:

Validator for Object Attributes - wxPyWiki
DataFormatters - wxPyWiki

There's also a Validator demo in the wxPython demo.

Mike

_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

Werner F. Bruhin wrote:

Adam Huffman wrote:

Mike Driscoll wrote:

Hello

I'm writing a simple app to take some details from users at login.
So far I have setup validation to ensure that the various text fields
are filled in and to collect the input from these fields.

However, in one case the text field should only contain some text if a
checkbox has been checked. In other words, the validator for this
text field only needs to run if the checkbox has been checked.
Clearly the validation can't take place immediately the checkbox is
clicked as then the user won't have any time to fill the text field.

I would be grateful for any suggestions as this is my first wxPython project.

Adam

If I were you, I would set the text control to disabled until the checkbox is checked. Then in the checked event handler, I would enable the text control. Text controls accept validators as part of their instantiation, so if you create it with one already linked, you won't need to add it later. I'm not even sure you can add one after it's been created. Anyway, the validator doesn't do anything until the user actually starts typing into the text control.

Thanks for the advice. I've tried to do that, but a validator is being called as soon as the text control is enabled. I've based my code on the wxPIA examples that came with my installation, in the Chapter-09 directory. Here's the relevant code:

class MyDialog(wx.Dialog):
   def __init__(self, data):
             wx.Dialog.__init__(self, None, wx.ID_ANY, 'Validation test', pos=(100, 100),
                         size=(1000, 700))

       text = wx.StaticText(self, -1, "User name and account details",
                            (20, 10))
       text.SetFont(wx.Font(14, wx.SWISS, wx.NORMAL, wx.BOLD))

       self.text2 = wx.TextCtrl(self, -1, "Test text", size=(175, -1),
                                pos=(20, 150), validator=DataXferValidator(data, "account"))

       self.acctick_c = wx.CheckBox(self, -1, "Tick if you don't know your account details",
                               (20, 330))
       self.acctick_l = wx.StaticText(self, -1, "If ticked, please enter your e-mail address:",
                                 pos=(20, 380))
       self.acctick_t = wx.TextCtrl(self, -1, "", size=(175, -1),
                               pos=(330, 380), validator=DataXferValidator(data, "email") )
       self.acctick_t.Disable()
       self.acctick_l.Disable()
       self.acctick_c.Bind(wx.EVT_CHECKBOX, self.ShowTextCtrl)

       self.okay = wx.Button(self, wx.ID_OK, pos=(500, 500))
       self.okay.SetDefault()

   def ShowTextCtrl(self, event):
       self.acctick_t.Enable()
       self.acctick_l.Enable()

At the moment the validation works as expected for the first text field. For the second text filed, which is disabled until the box is checked, the validation is called anyway, even though the user can't edit it.

I use validators mostly for data transfer, but I believe that on InitDialog only the TransferDataToWindow is run, while Validate is called either by you in the code or on a wxDialog when the OK button is clicked.

Yes, that's the behaviour I'm looking for i.e. validation should occur when OK is clicked. However, I only want the acctick_t
window to be validated if the box has been checked.

Looking at wxPIA chapter 9 I see that there is an OnChar validation, maybe in your case you want to do whatever you check in the Validate method instead.

That's what's happening now, a simple check that some text has been entered.

Do I need to add another test in the validation code, to ensure the window has been enabled?

I think that is needed to, you might also check if it IsModified and only write it back to the DB if it is.

I can't see an isEnabled attribute for wx.TextCtrl - do you know how to do that kind of test?

Adam

Mike Driscoll wrote:

Adam,

Thanks for the advice. I've tried to do that, but a validator is being called as soon as the text control is enabled. I've based my code on the wxPIA examples that came with my installation, in the Chapter-09 directory. Here's the relevant code:

class MyDialog(wx.Dialog):
   def __init__(self, data):
             wx.Dialog.__init__(self, None, wx.ID_ANY, 'Validation test', pos=(100, 100),
                         size=(1000, 700))

       text = wx.StaticText(self, -1, "User name and account details",
                            (20, 10))
       text.SetFont(wx.Font(14, wx.SWISS, wx.NORMAL, wx.BOLD))

       self.text2 = wx.TextCtrl(self, -1, "Test text", size=(175, -1),
                                pos=(20, 150), validator=DataXferValidator(data, "account"))

       self.acctick_c = wx.CheckBox(self, -1, "Tick if you don't know your account details",
                               (20, 330))
       self.acctick_l = wx.StaticText(self, -1, "If ticked, please enter your e-mail address:",
                                 pos=(20, 380))
       self.acctick_t = wx.TextCtrl(self, -1, "", size=(175, -1),
                               pos=(330, 380), validator=DataXferValidator(data, "email") )
       self.acctick_t.Disable()
       self.acctick_l.Disable()
       self.acctick_c.Bind(wx.EVT_CHECKBOX, self.ShowTextCtrl)

       self.okay = wx.Button(self, wx.ID_OK, pos=(500, 500))
       self.okay.SetDefault()

   def ShowTextCtrl(self, event):
       self.acctick_t.Enable()
       self.acctick_l.Enable()

At the moment the validation works as expected for the first text field. For the second text filed, which is disabled until the box is checked, the validation is called anyway, even though the user can't edit it.

Do I need to add another test in the validation code, to ensure the window has been enabled?

Probably. I've never used validators on disabled controls, so I can't be sure. Werner had some good ideas too, so be sure to read his answer. I usually use the validators to force the user to enter the type of data I want and if they fail to do so, I display an error message. Thus, I never send anything anywhere unless the data is correct. If you are doing database manipulation in your validator method, you might want to consider refactoring. The GUI code should be as decoupled from the data as possible.

Thanks for taking a look. I've now got around this by making a new instance of the TextCtrl with the validator, once the box is checked. Seems like a bit of a hack but it works...

Adam

Adam,

Adam Huffman wrote:

...

I can't see an isEnabled attribute for wx.TextCtrl - do you know how to do that kind of test?

It inherits it from wx.Window, but it is IsEnabled - watch out for starting caps.

Werner