I’m working on a simple program that collects and checks user-input. In addition to displaying
a message box if the user-supplied input fails the checks, I’d also like to add a prompt
just to the right of the input field telling the user what type of data is required. To accomplish this I’ve created a single-row FlexGridSizer consisting of the following:
[(wx.StaticText, “Name”), (wx.TextCtrl, “user inputs here”), (wx.StaticText, “Input Guidance”)]
On initialization the “Input Guidance” widget is hidden. If the user fails to enter anything in provided field, and then hits the OK button, I want three things to happen
- Field changes colour to alert user to a problem
- The “input guidance” widget (the third in the above row) becomes visible
- The DialogBox is automatically resized to take account of the now visible widget
So far I can only get (1) to work, and am looking for help with (2) and (3).
import wx
class Not_Empty(wx.PyValidator):
def __init__(self):
wx.PyValidator.__init__(self)
def Clone(self):
return Not_Empty()
################################################################################
def Validate(self, win):
""""""
evt_location = self.GetWindow()
val = evt_location.GetValue()
if val == "":
evt_location.SetBackgroundColour(wx.Color(250,200,230))
MyDialog().nameWarning_ST.Show(True)
return False
else:
return True
################################################################################
def TransferToWindow(self):
return True
def TransferFromWindow(self):
return True
class MyDialog(wx.Dialog):
def __init__(self):
wx.Dialog.__init__(self, parent=None, id=-1, title="Getting Input", style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
# Create field labels
name = wx.StaticText(self, -1, "Name")
# Create user-input widgets
name_TC = wx.TextCtrl(self, validator=Not_Empty())
# Create and hide warning boxes
self.nameWarning_ST = wx.StaticText(self, label="Field cannot be left empty", name="emptyAlert")
# to see what I want the dialog to look like AFTER the user has entered an
# empty string change 'False' to 'True' in the line below.
self.nameWarning_ST.Show(False)
# Create accept/cancel buttons
btns = self.CreateButtonSizer(flags=wx.OK|wx.CANCEL)
self.mainSizer = wx.BoxSizer(wx.VERTICAL)
fgs = wx.FlexGridSizer(cols = 3, rows = 1)
fgs.AddMany([(name, -1, wx.ALL, 5), (name_TC, -1, wx.ALL, 5), (self.nameWarning_ST, -1, wx.ALL, 5)])
self.mainSizer.AddMany([(fgs, 1, wx.ALL, 0), (btns, 1, wx.ALL|wx.EXPAND, 5)])
self.SetSizer(self.mainSizer)
self.mainSizer.Fit(self)
if __name__ == '__main__':
app = wx.App()
dlg = MyDialog()
dlg.Center()
dlg.ShowModal()
dlg.Destroy()
app.MainLoop()
EDIT: For the new question(s), I would use pubsub to solve this. Put a listener the init of the MyDialog class and then publish a message to it when the Validate method is run in the other class. In the message handler that you will theoretically create in MyDialog, you’ll want Show your other widget and call Layout() on the dialog. That should cause it to resize appropriately.
You can read a tutorial on pubsub here: http://www.blog.pythonlibrary.org/2010/06/27/wxpython-and-pubsub-a-simple-tutorial/
The following was for the original question:
Your Validate method doesn’t ever fire, so I rearranged your Validate and OnChar methods to look like the following:
Also note that I imported the string module to makes things a little easier. The code probably needs some clean up, but it worked on my machine.