How best to prevent user leaving a textbox if invalid text?

Hi,

Goal: prevent user leaving a textbox if the text is invalid, whether for a button or any other control.
Technique: Bind the EVT_KILL_FOCUS event to the textbox.
Problem: Clicking on a button is allowed even if the data in the textbox is invalid.
Question: Can this approach (using kill focus) be made to work? Or are validators the simplest way of achieving the desired result?

A test demo is below:

import wx

class TestDlg(wx.Dialog):
    def __init__(self):
        wx.Dialog.__init__(self, None, title="test", size=(500, 500))
        self.panel = wx.Panel(self)
        szr = wx.BoxSizer(wx.VERTICAL)
        lblInstructions = wx.StaticText(self.panel, -1,
            "Clicking on 'Click Here' should not leave 'Stuck here?' but OK should")
        self.txtStayHere = wx.TextCtrl(self.panel, -1, "Stuck here?")
        self.txtStayHere.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
        self.txtStayHere.SetFocus()
        txtOther = wx.TextCtrl(self.panel, -1, "Click here")
        btnOK = wx.Button(self.panel, wx.ID_OK)
        btnOK.Bind(wx.EVT_BUTTON, self.OnOK)
        szr.Add(lblInstructions)
        szr.Add(self.txtStayHere)
        szr.Add(txtOther)
        szr.Add(btnOK)
        self.panel.SetSizer(szr)

    def OnKillFocus(self, event):
        self.txtStayHere.SetFocus()
        # no event.Skip()

    def OnOK(self, event):
        wx.MessageBox("I'm OK but I shouldn't see this!")

if __name__ == "__main__":
    app = wx.PySimpleApp()
    dlg = TestDlg()
    dlg.ShowModal()
    app.MainLoop()

All the best, Grant

Hi,

···

On Oct 2, 2:27 am, Grant Paton-Simpson <gr...@p-s.co.nz> wrote:

Question: Can this approach (using kill focus) be made to work? Or are
validators the simplest way of achieving the desired result?

I would suggest validators, which are easy to use (see demo or Robin's
book).
You can validate on the fly or not.
But wx gurus will advise you better than me...

Dominique

Grant,

Grant Paton-Simpson wrote:

Hi,

Goal: prevent user leaving a textbox if the text is invalid, whether for a button or any other control.
Technique: Bind the EVT_KILL_FOCUS event to the textbox.
Problem: Clicking on a button is allowed even if the data in the textbox is invalid.
Question: Can this approach (using kill focus) be made to work? Or are validators the simplest way of achieving the desired result?
  

I am not sure that a kill focus approach will work, keep in mind that the user can also click outside your application and only come back to it later.

I use wx.lib.masked controls (you can all do it with standard controls, but the masked controls offer a lot of validation stuff) and then on save button I validate all the child controls which in my case are on the same panel as the button.

Werner

It looks like I should learn more about masked controls. Thanks for
that.

BTW my real code uses a validator with OnChar so that only letters,
numbers, and underscores can be entered (plus backspace and both types
of delete, including the numberpad one wx.WXK_NUMPAD_DELETE).
Additionally, the validator checks that the text entered isn't already
used. There was a bit of scaffolding required to use a validator but
the result is good.

One thing that initially tripped me up was how to call Validate
successfully. The code below illustrates a successful approach when
using a panel as the container for widgets.

        # NB must run Validate on the panel because the objects are
contained by
        # that and not the dialog itself.
        # http://www.nabble.com/validator-not-in-a-dialog-td23112169.html
        if not self.panel.Validate(): # runs validators on all assoc
controls
            return True

···

On Oct 3, 3:06 am, werner <wbru...@free.fr> wrote:

Grant,

Grant Paton-Simpson wrote:
> Hi,

> Goal: prevent user leaving a textbox if the text is invalid, whether for
> a button or any other control.
> Technique: Bind the EVT_KILL_FOCUS event to the textbox.
> Problem: Clicking on a button is allowed even if the data in the textbox
> is invalid.
> Question: Can this approach (using kill focus) be made to work? Or are
> validators the simplest way of achieving the desired result?

I am not sure that a kill focus approach will work, keep in mind that
the user can also click outside your application and only come back to
it later.

I use wx.lib.masked controls (you can all do it with standard controls,
but the masked controls offer a lot of validation stuff) and then on
save button I validate all the child controls which in my case are on
the same panel as the button.

Werner