title: How do I validate an entry widget in python?
body: <p>I'm creating a GUI using Tkinter that is used to collect information from a user. I need to validate:</p>
  
  <ul>
  <li>First and Last name only contain letters, apostrophes, and dashes</li>
  <li>Address</li>
  <li>Phone number has the correct number of digits</li>
  <li>Valid birthday (Feb 31 doesn't exist and birth year between 1900 and 2014)</li>
  <li>Email address contains '@' and '.'</li>
  </ul>
  
  <p>Here is my code:</p>
  
  <pre><code>from tkinter import *
  import datetime
  
  class tkwindow:
  
  def __init__(self):
  
      window = Tk() # Create window
      window.title("Contact Form") # Give window a title
  
      menubar = Menu(window) # Create menu bar
      window.config(menu = menubar) # Display menu bar
  
      '''Using the pulldown menu allows easier access to the menu items instead of using a pop-up menu '''
  
      # Create pulldown menu and add to menu bar
      messagesMenu = Menu(menubar, tearoff = 0)
      menubar.add_cascade(label = "Messages", menu = messagesMenu)
      messagesMenu.add_command(label = "Send a Birthday Greeting", command = self.bdayGreeting)
      messagesMenu.add_command(label = "Print Address", command = self.printAddress)
  
      # Create another menu option
      endMenu = Menu(menubar, tearoff = 0)
      menubar.add_cascade(label = "End", menu = endMenu)
      endMenu.add_command(label = "Reset Form", command = self.resetForm)
      endMenu.add_command(label = "Exit Program", command = window.quit)
  
      # Using Label widget
      labelFirst = Label(window, text = "First Name: ").grid(row = 1, column = 1, sticky = E)
      labelLast = Label(window, text = "Last Name: ").grid(row = 2, column = 1, sticky = E)
      labelAddress = Label(window, text = "Address: ").grid(row = 3, column = 1, sticky = E)
      labelPhone = Label(window, text = "Phone Number (8005551234): ").grid(row = 4, column = 1, sticky = E)
      labelBday = Label(window, text = "Birthday (MM/DD/YYYY): ").grid(row = 5, column = 1, sticky = E)
      labelEmail = Label(window, text = "Email Address (user@domain.com): ").grid(row = 6, column = 1, sticky = E)
  
      # Using Entry widget
      self.firstName = StringVar()
      entryFirst = Entry(window, textvariable = self.firstName, justify = LEFT).grid(row = 1, column = 2, sticky = W)
  
      self.lastName = StringVar()
      entryLast = Entry(window, textvariable = self.lastName, justify = LEFT).grid(row = 2, column = 2, sticky = W)
  
      self.address = StringVar()
      entryAddress = Entry(window, textvariable = self.address, justify = LEFT).grid(row = 3, column = 2, sticky = W)
  
      self.phone = StringVar()
      entryPhone = Entry(window, textvariable = self.phone, justify = LEFT).grid(row = 4, column = 2, sticky = W)
  
      self.bday = StringVar()
      entryBday = Entry(window, textvariable = self.bday, justify = LEFT).grid(row = 5, column = 2, sticky = W)
  
      self.email = StringVar()
      entryEmail = Entry(window, textvariable = self.email, justify = LEFT).grid(row = 6, column = 2, sticky = W)
  
      self.errorLblFirst = Label(window, fg = "red")
      self.errorLblFirst.grid(row = 1, column = 3)
  
      self.errorLblLast = Label(window, fg = "red")
      self.errorLblLast.grid(row = 2, column = 3)
  
      self.errorLblAddress = Label(window, fg = "red")
      self.errorLblAddress.grid(row = 3, column = 3)
  
      self.errorLblPhone = Label(window, fg = "red")
      self.errorLblPhone.grid(row = 4, column = 3)
  
      self.errorLblBday = Label(window, fg = "red")
      self.errorLblBday.grid(row = 5, column = 3)
  
      self.errorLblEmail = Label(window, fg = "red")
      self.errorLblEmail.grid(row = 6, column = 3)
  
      # Using Button widget
      buttonSubmit = Button(window, text = "Submit", command = self.submit).grid(row = 7, column = 2, sticky = E)
  
      window.mainloop()
  
  def resetForm(self):
  
      self.firstName.set('')
      self.errorLblFirst["text"] = ''
      self.lastName.set('')
      self.errorLblLast["text"] = ''
      self.address.set('')
      self.errorLblAddress["text"] = ''
      self.phone.set('')
      self.errorLblPhone["text"] = ''
      self.bday.set('')
      self.errorLblBday["text"] = ''
      self.email.set('')
      self.errorLblEmail["text"] = ''
  
  def validFirst(self):
  
      for letter in self.firstName.get():
          if not letter.isalpha() and letter not in "'-":
              self.errorLblFirst["text"] = " * Letters, apostrophes('), and hypens(-) only"
              return False
  
      return True
  
  def validLast(self):
  
      for letter in self.lastName.get():
          if not letter.isalpha() and letter not in "'-":
              self.errorLblLast["text"] = " * Letters, apostrophes('), and hypens(-) only"
              return False
  
      return True
  
  def validAddress(self):
  
      for letter in self.address.get():
          if not letter.isalnum() and letter not in "'- .,":
              self.errorLblAddress["text"] = " * No special characters"
              return False
  
      return True
  
  def validPhone(self):
  
      D = 0
  
      for number in self.phone.get():
          if number.isdigit():
              D += 1
          if D == 10:
              return True
          else:
              self.errorLblPhone["text"] = " * Must be 10-digit phone number without spaces"
              return False
  
      return True
  
  def validBday(self):
  
      '''try:
          valid_date = datetime.datetime.strptime(str(self.bday), '%m/%d/%Y')
      except ValueError:
          print('Invalid date!')'''
      return True
  
  def validEmail(self):
  
      for letter in self.email.get():
          if not letter.isalnum() and letter not in "@.":
              self.errorLblEmail["text"] = " * Must have @ and ."
              return False
  
      return True
  
  def bdayGreeting(self):
      if self.validBday() and self.validFirst() == True:
          print("Happy Birthday" + self.firstName.get() + "\n" + self.bday.get())
  
  def printAddress(self):
      if self.validFirst() and self.validLast() and self.validAddress() == True:
          print(self.firstName.get() + " " + self.lastName.get() + "\n" + self.address.get())
  
  
  def submit(self):
      self.validFirst()
      self.validLast()
      self.validAddress()
      self.validPhone()
      self.validBday()
      self.validEmail()
  
  tkwindow()
  </code></pre>
  
  <p>I have a couple questions.</p>
  
  <ol>
  <li>Starting from def validFirst(self), how do I validate the different entry fields? I keep getting <code>NameError: name "asdf" is not defined</code>, <code>SyntaxError: unexpected EOF while parsing</code>, and <code>TypeError: 'int' object is not subscriptable</code> when I modify the code and I'm still stuck on validFirst(self).</li>
  <li>I have a set of labels in column 3 reserved for error messages: <code>errorLblFirst = Label(window, text = "                ", fg = "red").grid(row = 1, column = 3)</code>. Is it possible to set it to <code>" * Invalid Entry", fg = "red"</code> when the validation for that entry fails? Is there another way to get error messages to show?</li>
  </ol>
  
  <p>Thanks in advance for the input!</p>
  
  <p>Edit: I updated to my latest code. Most of the validation works now except for <code>validBday</code> and <code>validEmail</code> if you could check it out.</p>