John Clark wrote:
There is a style flag that is discussed called wx.WS_EX_VALIDATE_RECURSIVELY
and the book says: "If the wx.WS_EX_VALIDATE_RECURSIVELY extra style is set
for the window, Validate() of all the child windows is also called. If any
of the validations fail, Validate returns False." I originally took this to
mean that in my example, if the style included the
WS_EX_VALIDATE_RECURSIVELY flag that the validate routines on each of the
three TextCtrl widgets would be called and after all Validate() functions
had executed if any of them had returned False, the entire Dialog would fail
validation. However, that's not the behavior that I am seeing in the
window. Based on what I am seeing the Dialog do, I now believe that the
statement above means that if you have several levels of nested controls on
the frame, that the validate process will traverse the containment hierarchy
of all controls on the window and will fail validation with the first
control that returns False from the validate function.Is this an accurate understanding of the behavior of the
wx.WS_EX_VALIDATE_RECURSIVELY style option?
Correct. Also, there is a difference between a widget's Validate method and the validator's Validate method. It's the widget's Validate that is affected by the wx.WS_EX_VALIDATE_RECURSIVELY flag. For historical reasons the default behavior of widget.Validate() is to loop through the widget's immediate children, check if each has a validator, and if so call the validator's Validate, and bail out if any of them return False. The wx.WS_EX_VALIDATE_RECURSIVELY flag simply adds a call to child.Validate() to the loop. You can see the code for this in the wxWindowBase::Validate() here:
And if so, is there any way to
get the Dialog to validate all controls on the dialog and to then aggregate
the results? The behavior I would ultimately like to implement is that when
the OK button is pressed, Validate() will be called for each of the three
TextCtrls on the dialog, and should any of the three fail, the message box
will then pop and ask the user to fill in the fields with pink backgrounds.
I realize that this would require chaning the Validate() function so that
each Validate function wasn't responsible for popping the MessageBox.My idea towards implementing this was to put the contents of the dialog onto
a panel object, and create a validator for the panel that would have a
Validate() method as follows:def Validate(self, parent):
panel = self.GetWindow()
children = panel.GetChildren()
result = all([eachChild.Validate() for eachChild in children])
if not result:
wx.MessageBox("This field must contain some text!", "Error")
return resultHowever, what I am seeing when I do this is that the TextCtrl, which should
return False from a eachChild.Validate() call, is returning True in this
routine. If I set the dialog to "wx.WS_EX_VALIDATE_RECURSIVELY" then the
validate on the TextCtrl fails when called as part of the recursive
processing, but not when the panel is validated. Is it possible to
directly call Validate() on a widget like this? If so, is there a reason
that I am not getting the proper response in my method?
The assumption that widget.Validate makes is that you are not interested in its own validator, but in it's children's validators (because it is intended for use on container windows.) Since a textctrl doesn't have any children then calling it's Validate() simply returns True.
To do what you want you'll need to see if each child has a validator and then call its Validate(), similar to what the wxWindowBase::Validate does.
ยทยทยท
--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!