[wxPython] wxValidator Problems

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

[wxPython] wxValidator Problems

Cavanaugh, Craig
Hi,

I've been struggling with wxValidator for a few hours now and have not been
able to find any answers in the archives

I have the following code inside of a derived wxDialog.  When I do a
dlg.ShowModal(), I get a warning box saying "Could not transfer data to
Window"

After closing the dialog (clicking OK button, after entering a float into
the control) I get a GPF (Windows NT, latest interim release)

I haven't figured out what to do with TransferToWindow() and
TransferFromWindow() yet.
Is this the source of the GPF?

Note: the original demo works fine.


Thanks,
        Craig

<snip>

fltValidator = floatValidator()        

Tbox = wxBoxSizer(wxHORIZONTAL)
Tbox.Add(wxStaticText(self, -1, "Initial Balance"),0,wxALL,5)
Tbox.Add(wxTextCtrl(self, 13, str(self.initBalance), validator =
fltValidator),0,wxALL,5)
# Tbox.Add(wxTextCtrl(self, 13, "", validator = fltValidator),0,wxALL,5)
box1.Add(Tbox,0,wxALL,2)

<snip>

# ---------------------------------------------------------------------
# validator.py
# copied and tweaked from wxPython validator example

from wxPython.wx import *

class floatValidator(wxPyValidator):
       
    def __init__(self, pyVar=None):
        wxPyValidator.__init__(self)
        self.numList = ['1','2','3','4','5','6','7','8','9','0','.']
        EVT_CHAR(self, self.OnChar)

    def Clone(self):
        return floatValidator()

    # **** not sure what to do here yet ****
    # def TransferToWindow(self):
    #     return true

    # def TransferFromWindow(self):
    #    return true

    def Validate(self, win):
        # print 'validate'
       
        tc = wxPyTypeCast(win, "wxTextCtrl")
        val = tc.GetValue()        

        for x in val:
            if x not in self.numList:
                return false

        return true

    def OnChar(self, event):        
        key = event.KeyCode()
        if key < WXK_SPACE or key == WXK_DELETE or key > 255:
            event.Skip()
            return
       
        if chr(key) in self.numList:
            event.Skip()
            return

        if not wxValidator_IsSilent():
            wxBell()

        # Returning without calling even.Skip eats the event before it
        # gets to the text control
        return
#---------------------------------------------------------------------------
--------------

_______________________________________________
wxPython-users maillist  -  [hidden email]
http://starship.python.net/mailman/listinfo/wxpython-users



Reply | Threaded
Open this post in threaded view
|

Re: [wxPython] wxValidator Problems

Robin Dunn
>
> I've been struggling with wxValidator for a few hours now and have not been
> able to find any answers in the archives
>
> I have the following code inside of a derived wxDialog.  When I do a
> dlg.ShowModal(), I get a warning box saying "Could not transfer data to
> Window"
>
> After closing the dialog (clicking OK button, after entering a float into
> the control) I get a GPF (Windows NT, latest interim release)
>
> I haven't figured out what to do with TransferToWindow() and
> TransferFromWindow() yet.
> Is this the source of the GPF?
>

If you uncomment the Transfer functions then it works.  Apparently wxDialog
automatically calls wxPanel::InitDialog (wxPanel does not) so it calls the
Transfer functions to allow the validator to move data in and out of the
dialog fields.  It shouldn't be crashing without them though, I'll check into
that...

The basic concept behind the Transfer methods is to be able to automatically
load the entry fields from program variables, and once the data has been
validated to put it back in the program variables.  In C++ they just pass
pointers to variables to the validators and it works fine.  In Python since
things like numbers and strings are immutable it is not so easy.  You can get
the value easy enough but putting it back is not.  However it would work just
fine getting/setting attributes of an object, maybe something like this:



from wxPython.wx import *
import string

class floatValidator(wxPyValidator):

    def __init__(self, obj=None, attrName=""):
        wxPyValidator.__init__(self)
        self.numList = ['1','2','3','4','5','6','7','8','9','0','.']
        EVT_CHAR(self, self.OnChar)
        self.obj = obj
        self.attrName = attrName

    def Clone(self):
        return floatValidator(self.obj, self.attrName)

    def TransferToWindow(self):
        if self.obj and hasattr(self.obj, self.attrName):
            tc = wxPyTypeCast(self.GetWindow(), "wxTextCtrl")
            tc.SetValue(str(getattr(self.obj, self.attrName)))
        return true

    def TransferFromWindow(self):
        if self.obj and self.attrName:
            tc = wxPyTypeCast(self.GetWindow(), "wxTextCtrl")
            text = tc.GetValue()
            setattr(self.obj, self.attrName, string.atof(text))
        return true


    def Validate(self, win):
        tc = wxPyTypeCast(self.GetWindow(), "wxTextCtrl")
        val = tc.GetValue()

        for x in val:
            if x not in self.numList:
                return false

        return true

    def OnChar(self, event):
        key = event.KeyCode()
        if key < WXK_SPACE or key == WXK_DELETE or key > 255:
            event.Skip()
            return

        if chr(key) in self.numList:
            event.Skip()
            return

        if not wxValidator_IsSilent():
            wxBell()

        # Returning without calling even.Skip eats the event before it
        # gets to the text control
        return



class MyDialog(wxDialog):
    def __init__(self, parent):
        wxDialog.__init__(self, parent, -1, "hello")

        self.theValue =  555.12
        fltValidator = floatValidator(self, "theValue")

        Vbox = wxBoxSizer(wxVERTICAL)
        Tbox = wxBoxSizer(wxHORIZONTAL)
        Tbox.Add(wxStaticText(self, -1, "Initial Balance"), 0, wxALL,5)
        Tbox.Add(wxTextCtrl(self, 13, "123.45", validator = fltValidator,
                            size=(100, -1)), 0, wxALL,5)

        Vbox.Add(Tbox, 0, 0)

        Tbox = wxBoxSizer(wxHORIZONTAL)
        Tbox.Add(wxButton(self, wxID_OK, "Ok"), 0, wxALL,5)
        Tbox.Add(wxButton(self, wxID_CANCEL, "Cancel"), 0, wxALL,5)

        Vbox.Add(Tbox, 0, 0)

        self.SetAutoLayout(true)
        self.SetSizer(Vbox)
        Vbox.Fit(self)


class TestFrame(wxFrame):
    def __init__(self, parent):
        wxFrame.__init__(self, parent, -1, "Testing...", size=(150,75))
        wxButton(self, 25, "Click Me")
        EVT_BUTTON(self, 25, self.OnClick)


    def OnClick(self, event):
        dlg = MyDialog(self)
        dlg.ShowModal()
        print dlg.theValue
        dlg.Destroy()



app = wxPySimpleApp()
frame = TestFrame(None)
frame.Show(true)
app.MainLoop()







_______________________________________________
wxPython-users maillist  -  [hidden email]
http://starship.python.net/mailman/listinfo/wxpython-users