I'm creating a GUI using Tkinter that is used to collect information from a user. I need to validate:
First and Last name only contain letters, apostrophes, and dashes
Address
Phone number has the correct number of digits
Valid birthday (Feb 31 doesn't exist and birth year between 1900 and 2014)
Email address contains '#' and '.'
Here is my 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()
I have a couple questions.
Starting from def validFirst(self), how do I validate the different entry fields? I keep getting NameError: name "asdf" is not defined, SyntaxError: unexpected EOF while parsing, and TypeError: 'int' object is not subscriptable when I modify the code and I'm still stuck on validFirst(self).
I have a set of labels in column 3 reserved for error messages: errorLblFirst = Label(window, text = " ", fg = "red").grid(row = 1, column = 3). Is it possible to set it to " * Invalid Entry", fg = "red" when the validation for that entry fails? Is there another way to get error messages to show?
Thanks in advance for the input!
Edit: I updated to my latest code. Most of the validation works now except for validBday and validEmail if you could check it out.
errorLblFirst = Label(...).grid(...)
This way you assign result of grid() to errorLblFirst but grid() always returns None
Always do it this way
errorLblFirst = Label(...)
errorLblFirst.grid(...)
And now you can do (for example)
errorLblFirst["text"] = " * Invalid Entry"
errorLblFirst["fg"] = "red"
EDIT:
You forgot len() in for i in range(first): in validFirst()
And you don't need eval().
(You got the same problem in validPhone())
F = 0
fName = True
first = self.firstName.get() # without eval()
for i in range(len(first)): # len()
if first[i].isdigit():
F += 1
if F > 0:
return False
else:
return fName
return fName
but you could do this shorter
for letter in self.firstName.get():
if letter.isdigit():
return False
return True
if you need only letters (no space, commas, etc.) you could do this
return self.firstName.get().isalpha()
EDIT:
I see First Name can have apostrophes, and dashes
for letter in self.firstName.get():
if not letter.isalpha() and letter not in "'-":
return False
return True
EDIT: problem with self.phone and StringVar
self.phone is StringVar() - not string
but StringVar() has .get() to get string
for number in range(len( self.phone.get() )):
By the way: you can do for loop more pythonic - without range(len())
for char in self.phone.get():
if char.isdigit():
EDIT: problem with validEmail() and validBday()
Email validation needs more if.
For example you could add
email = self.email.get()
if '#' not in email and '.' not in email::
print( 'email needs # and . at the same time')
but '.#' will pass this test :/
Real email validation is more complicated.
See valid email examples: https://fightingforalostcause.net/content/misc/2006/compare-email-regex.php
self.bday is StringVar - use self.bday.get() in place of str(self.bday)
EDIT:
def validPhone(self):
D = 0
for number in self.phone.get():
if number.isdigit():
D += 1
# outside
if D == 10:
return True
else:
self.errorLblPhone["text"] = " * Must be 10-digit phone number without spaces"
return False
return True
or even
def validPhone(self):
# remove previous error message
self.errorLblPhone["text"] = ""
D = 0
for number in self.phone.get():
if number.isdigit():
D += 1
if D != 10:
self.errorLblPhone["text"] = " * Must be 10-digit phone number without spaces"
return False
return True
If number can have only 10 digits (no space, no - , etc):
def validPhone(self):
# remove previous error message
self.errorLblPhone["text"] = ""
D = True
for number in self.phone.get():
if not number.isdigit():
D = False
break
if not D or len(number) != 10:
self.errorLblPhone["text"] = " * Must be 10-digit phone number without spaces"
return False
return True
Related
I am having a problem with adding status bar at the bottom of my program. When I do status.pack() it gives me this error : _tkinter.TclError: cannot use geometry manager grid inside . which already has slaves managed by pack. In My (
def init(self): ) If I delete (self.grid(sticky = W+E+N+S) then the window pops up an then the status bar is on the window, but then the rest of the program isn't there. I was wondering if someone give some insight on how to fix this
from tkinter.constants import END
from tkinter import ttk
from tkinter import *
from tkinter import font
from tkinter import messagebox
import tkinter as tk
import turtle
import random
from tkinter import filedialog
from PIL import Image
class App(Frame):
**********************************************************************************************************************************************************************************************************************8888
'''The code below Creates a Menu Bar across the top of the window '''
App = Tk()
menu = Menu (App)
App.config(menu = menu)
'''Lines 20 - 22 are basic setup for drop down meun box at the top of the page.'''
fileMenu = Menu(menu, tearoff = 0)
fileMenu.add_command(label = "New Project", command = turtle)
fileMenu.add_command(label = "Open", command = turtle)
fileMenu.add_command(label = "Save", command = turtle)
fileMenu.add_command(label = "Save as", command = turtle)
fileMenu.add_command(label = "Close", command = turtle)
menu.add_cascade(label = "File", menu = fileMenu)
fileMenu.add_separator()
'''This bit of code adds a separator between the buttons on the drop down menu.'''
fileMenu.add_command(label = "Exit", command = App.quit)
editMenu = Menu(menu, tearoff = 0)
editMenu.add_command(label = "Cut", command = turtle)
editMenu.add_command(label = "Copy", command = turtle)
editMenu.add_command(label = "Paste", command = turtle)
editMenu.add_command(label = "Delete", command = turtle)
editMenu.add_command(label = "Select All", command = turtle)
menu.add_cascade(label = "Edit", menu = editMenu)
helpMenu = Menu(menu, tearoff = 0)
helpMenu.add_command(label = "Help Index", command = turtle)
helpMenu.add_command(label = "About", command = turtle)
menu.add_cascade(label = "Help", menu = helpMenu)
************************************************************************************************************************************************************************************************************************************
''' The code below creates a Status Bar Across the bottom of the page. '''
status = Label(App, text = "This is a status bar...", bd = 1, relief = SUNKEN, anchor = W)
status.pack()
******************************************************************************************************************************************************************************************************************************
def __init__(self):
'''Sets up the window and widgets.'''
Frame.__init__(self, bg = "white" ) #this sets the background color of the window.
self.master.title("Auto Body Buddy Estimator") #this is the title of the screen
self.master.geometry("600x600") #this is the specs for the window size
self.master.resizable(0, 0) #this makes the window none resizable
self.master.columnconfigure(0, weight = 1)
self.master.rowconfigure(0, weight = 1)
self.grid(sticky = W+E+N+S)
#!/usr/bin/python
'''import cgi, os
import cgitb; cgitb.enable()
form = cgi.FieldStorage()
# Get filename here.
fileitem = form['filename']
# Test if the file was uploaded
if fileitem.filename:
# strip leading path from file name to avoid
# directory traversal attacks
fn = os.path.basename(fileitem.filename)
open('/tmp/' + fn, 'wb').write(fileitem.file.read())
message = ('The file "' + fn + '" was uploaded successfully')
else:
message = 'No file was uploaded'
print """\
Content-Type: text/html\n
<html>
<body>
<p>%s</p>
</body>
</html>
""" % (message,) '''
***********************************************************************************************************************************************************************
''' Creates the nested frame for the Data pane for the image '''
self._dataPane1 = Frame(self)#, bg = "orange")
self._dataPane1.grid(row = 0, column = 0)
self._pictureImage = PhotoImage(file = "../logo.gif")
self._imageLabel = Label(self._dataPane1, image = self._pictureImage)
self._imageLabel.grid(row = 0, column= 0)
*********************************************************************************************************************************************************************
''' Creates the nested frame for the Data pane'''
self._dataPaneEntryInfo = Frame(self, bg = "white")
self._dataPaneEntryInfo.grid(row = 1, column = 0)
''' Label and field for First Name '''
self._firstNameLabel = Label(self._dataPaneEntryInfo, bg = "white", text = "First Name ")
self._firstNameLabel.grid(row = 0, column = 0)
self._firstNameVar = DoubleVar()
self._firstNameEntry = Entry(self._dataPaneEntryInfo, textvariable = self._firstNameVar)
self._firstNameEntry.grid(row = 0, column = 1)
''' Label and field for Last Name '''
self._LastNameLabel = Label(self._dataPaneEntryInfo, bg = "white", text = "Last Name ")
self._LastNameLabel.grid(row = 1, column = 0)
self._LastNameVar = DoubleVar()
self._LastNameEntry = Entry(self._dataPaneEntryInfo, textvariable = self._LastNameVar)
self._LastNameEntry.grid(row = 1, column = 1)
''' Label and field for Phone Number '''
self._phoneNumberLabel = Label(self._dataPaneEntryInfo, bg = "white", text = "Phone Number ")
self._phoneNumberLabel.grid(row = 2, column = 0)
self._phoneNumberVar = DoubleVar()
self._phoneNumberEntry = Entry(self._dataPaneEntryInfo, textvariable = self._phoneNumberVar)
self._phoneNumberEntry.grid(row = 2, column = 1)
''' Label and field for Email '''
self._EmailLabel = Label(self._dataPaneEntryInfo, bg = "white", text = "Email Address ")
self._EmailLabel.grid(row = 3, column = 0)
self._EmailVar = DoubleVar()
self._EmailEntry = Entry(self._dataPaneEntryInfo, textvariable = self._EmailVar)
self._EmailEntry.grid(row = 3, column = 1)
''' Label and field for Address '''
self._addressLabel = Label(self._dataPaneEntryInfo, bg = "white", text = "Address \n (OPITIONAL) ")
self._addressLabel.grid(row = 4, column = 0)
self._addressVar = DoubleVar()
self._addressEntry = Entry(self._dataPaneEntryInfo, textvariable = self._addressVar)
self._addressEntry.grid(row = 4, column = 1)
*********************************************************************************************************************************************************************
''' Label and field for Year of the Car '''
self._yearLabel = Label(self._dataPaneEntryInfo, bg = "white", text = "Year ")
self._yearLabel.grid(row = 0, column = 2)
self._yearVar = DoubleVar()
self._yearEntry = Entry(self._dataPaneEntryInfo, textvariable = self._yearVar)
self._yearEntry.grid(row = 0, column = 3)
''' Label and field for Make of the Car '''
self._makeLabel = Label(self._dataPaneEntryInfo, bg = "white", text = "Make ")
self._makeLabel.grid(row = 1, column = 2)
self._makeVar = DoubleVar()
self._makeEntry = Entry(self._dataPaneEntryInfo, textvariable = self._makeVar)
self._makeEntry.grid(row = 1, column = 3)
''' Label and field for Model of the Car '''
self._modelLabel = Label(self._dataPaneEntryInfo, bg = "white", text = "Model ")
self._modelLabel.grid(row = 2, column = 2)
self._modelVar = DoubleVar()
self._modelEntry = Entry(self._dataPaneEntryInfo, textvariable = self._modelVar)
self._modelEntry.grid(row = 2, column = 3)
''' Label and field for Package of the Car '''
self._packageLabel = Label(self._dataPaneEntryInfo, bg = "white", text = "Package ")
self._packageLabel.grid(row = 3, column = 2)
self._packageVar = DoubleVar()
self._packageEntry = Entry(self._dataPaneEntryInfo, textvariable = self._packageVar)
self._packageEntry.grid(row = 3, column = 3)
''' Label and field for VIN # of the Car '''
self._vinLabel = Label(self._dataPaneEntryInfo, bg = "white", text = "VIN # ")
self._vinLabel.grid(row = 4, column = 2)
self._vinVar = DoubleVar()
self._vinEntry = Entry(self._dataPaneEntryInfo, textvariable = self._vinVar)
self._vinEntry.grid(row = 4, column = 3)
******************************************************************************************************************************************************************************************************
''' Creates the nested frame for the Data pane'''
self._dataPaneComment = Frame(self, bg = "black")
self._dataPaneComment.grid(row = 2, column = 0)
'''# Label and info field for Comment Box .'''
self._text = "Enter text here. "
self._outputArea = Text(self._dataPaneComment, width = 50, height = 10, wrap = WORD)
self._outputArea.grid(row = 0, column = 0, columnspan = 2)
*********************************************************************************************************************************************************************************************************
''' Creates the nested frame for the Button pane for the Submit'''
self._buttonPane = Frame(self) #this creates a box for the buttons to be placed in one area.
self._buttonPane.grid(row = 3, column = 0)#this gives the button pane a position in the GUI
''' Black and White button '''
self._button1 = Button(self._buttonPane, text = "SUBMIT", command = self._NameEntry)#This creates the button.
self._button1.grid(row = 0, column = 0) #This gives the button a position in the GUI.
********************************************************************************************************************************************************************************************************
def _NameEntry(self):
open("Results.txt", "w").close()
first = self._firstNameEntry.get()
last = self._LastNameEntry.get()
phone = self._phoneNumberEntry.get()
email = self._EmailEntry.get()
address = self._addressEntry.get()
year = self._yearEntry.get()
make = self._makeEntry.get()
model = self._modelEntry.get()
package = self._packageEntry.get()
vin = self._vinEntry.get()
with open("../" + first + " " + last + ".txt", "a") as the_file:
the_file.write("First Name: " + first + "\n" "Last Name: " + last + "\n" "Phone Number: " + phone + "\n" "Email: " + email + "\n"
"Address: " + address + "\n" "Year: " + year + "\n" "Make: " + make + "\n" "Model: " + model + "\n"
"Package: " + package + "\n" "Vin: " + vin + "\n")
'''open("Results.txt", "w").close()
last = self._LastNameEntry.get()
with open("../Results.txt", "a") as the_file:
the_file.write("Last Name: " + last)'''
'''first = self._firstNameEntry.get()
name = open("Results.txt", "w")
name.write("First Name: ".insert(first))
name.close()'''
def main():
'''Instantiate and pop up the window.'''
App().mainloop()
if __name__ == '__main__':
main()
I'm exactly sure on how to upload the gif file with this code.
The error message is telling you what's wrong. If you have already used one geometry manager within a widget you cannot use another.
e.g. - You cannot use both pack and grid within a frame. You must use one or the other.
You could make another widget and then use the seperate geometry manager within this widget but you would have to use the original manager to place it within the master widget.
This is my current code and it displays in a window but literally prints it the way I've typed it (obviously). But is there a way to write these so they are displayed as powers/exponents?
"
questionNum = 0
#SET QUESTIONS HERE
questions = [0,"Given that y = x^4 + 6x^1/2, find dy/dx","Write down the value of 125^1/3","Fully factorise 9x^2 - 25","Find the value of 8^5/3"]
answer1 = [0,"4x^4 + 3x^1/2","25","(3x-5)(3x+5)","1/2"]
answer2 = [0,"4x^3 + 6x^1/2","1/5","(3x+5)(3x+5)","Answer 2 (4)"]
answer3 = [0,"4x^3 + 6x^-1/2","5","(3x-5)(3x-5)","Answer 3 (4)"]
answer4 = [0,"4x^3 + 1/2x^-3/2","125","(9x+5)(x-5)","Answer 4 (4)"]
This is what it looks like:
rightanswers = [0,1,2,3,4] #These are the correct answers
"
This is the bit that needs to be changed. I've added the rest just in case you need any of it to see what's going on:
from tkinter import * #The TKinter module imported in order to create the menus
import sys #Invoke functions and statements - allows operations to work and searches for named modules i.e. TKinter
global questionNum #Connections between functinos and arrays
questionNum = 0
#SET QUESTIONS HERE
questions = [0,"Given that y = x^4 + 6x^1/2, find dy/dx","Write down the value of 125^1/3","Fully factorise 9x^2 - 25","Find the value of 8^5/3"] #This is the question bank which has been set up as an array
answer1 = [0,"4x^4 + 3x^1/2","25","(3x-5)(3x+5)","1/2"] #These are the possible answers - this is where multiple choice answers would go
answer2 = [0,"4x^3 + 6x^1/2","1/5","(3x+5)(3x+5)","Answer 2 (4)"]
answer3 = [0,"4x^3 + 6x^-1/2","5","(3x-5)(3x-5)","Answer 3 (4)"]
answer4 = [0,"4x^3 + 1/2x^-3/2","125","(9x+5)(x-5)","Answer 4 (4)"]
rightanswers = [0,1,2,3,4] #These are the correct answers
normal = Tk() #Build the TKinter
normal.geometry("850x350") #Set the size of the normal chess form to 850x350
normal.title("Normal Chess") #Sets a title for the normal chess form
normal.columnconfigure(1,minsize = 300) #This is whereabouts the question and answers are displayed
questionVar = StringVar() #Question will be a string
answerVar = IntVar() #Answers will be numbers
answerVar.set(1) #Questions can only have one solution
aText = StringVar() #Text for the answers - options
bText = StringVar()
cText = StringVar()
dText = StringVar()
qNoText = StringVar() #Questions text which is displayed to the user
questionText = StringVar()
normal.withdraw() #Allows the user to only select one option
title = Tk() #Builds the TKinter
title.title("Chess") #Title of the form
title.geometry("300x300") #The size of the image
watermark = PhotoImage(file = "watermark.gif") #Link to the image itself
Label(image = watermark).place(x=0,y=0,relwidth=1,relheight=1) #Places the image onto the form set on the x,y coordinates
title.withdraw()
menu = Tk() #Builds the TKinter
menu.title("Main Menu") #Displays 'Main Menu' on screen
menu.geometry("400x350") #Size of the form
p1var = StringVar() #Sets a variable for Player 1 and Player 2
p2var = StringVar()
def Quit(): #Quit function - allows the user to exit the program
menu.destroy()
title.destroy()
normal.destroy()
sys.exit() #Gets rid of all the modules
def play():
title.deiconify()
Label(title,text = "Enter Details:",font = ("Calibri",25)).grid(row = 1, column = 1)
#'Enter Details' font, size and location on the form
Label(title,text = "CHESS",font = ("Calibri",50)).grid(row = 0,column = 1)
#'CHESS' font, size and location on the form
Label(title, text = "Player 1: ").grid(row = 2,column = 0)
#'Player 1' font, size and location on the form
Entry(title,textvariable = p1var,width = 30).grid(row = 2,column = 1)
#Allows the user to input a string for the player 1 name
Label(title, text = "Player 2: ").grid(row = 3,column = 0)
#'Player 2' font, size and location on the form
Entry(title,textvariable = p2var,width = 30).grid(row = 3,column = 1)
#Allows the user to input a string for the player 2 name
Label(title,text = "Select Game Mode: ").grid(row = 4,column = 1)
#'Select Game Mode: ' font, size and location on the form
Button(title,command = lambda: playNormalChess(p1var.get(),p2var.get()),text = "Normal Chess").grid(row = 6,column = 1,sticky = W)
#Button for normal chess
Button(title,command = lambda: playSpeedChess(p1var.get(),p2var.get()),text = "Speed Chess").grid(row = 6,column = 1,sticky = E)
#Button for speed chess
Button(title,command = instructions,text = "Instructions").grid(row = 7,column = 1,pady =10)
#Button for instructions
def playNormalChess(p1,p2):
normal.deiconify()
t = Label(textvariable = qNoText,font = ("Arial",50)).grid(row = 0,column = 1,sticky = W,columnspan=2,padx = 20,pady =10)
#Functions for selection
q =Label(textvariable = questionVar,font = ("Arial",30)).grid(row = 1,column = 1,sticky = W,columnspan=2,padx = 20,pady =10)
#Font and size the questions are set in
a=Radiobutton(variable = answerVar,value = 1,textvariable = aText,font = ("Arial",18)).grid(row = 3,column = 1,pady =5,padx = 20,sticky = W)
#These are the radio buttons which are linked to the answers - set the font and the size of the text
b=Radiobutton(variable = answerVar,value = 2,textvariable = bText,font = ("Arial",18)).grid(row = 4,column = 1,padx = 20,sticky = W)
c=Radiobutton(variable = answerVar,value = 3,textvariable = cText,font = ("Arial",18)).grid(row =5,column = 1,pady = 5,padx = 20,sticky = W)
d=Radiobutton(variable = answerVar,value=4,textvariable = dText,font = ("Arial",18)).grid(row = 6,column = 1,padx = 20,sticky = W)
Button(text = "Submit",command = confirm).grid(row =0,column = 3,sticky = W,pady = 10) #Submit button to confirm their answers
newQuestion() #Calls the function for a new question
def confirm():
if messagebox.askyesno('Confirm','Are You Sure?'): #This is the conformation of the correct answer for the user
try:
if answerVar.get() == rightanswers[questionNum]: #If they select yes to confirm they are happy with the selection
# - it checks their answer with the correct answer and prints 'Right' or 'Wrong' depending on their answer
print("Right")
else:
print("Wrong")
newQuestion() #Once their question is answered, a new question will be presented to them
except IndexError:
print("No more Questions")
def newQuestion():
global questionNum
questionNum = questionNum + 1
try:
qNoText.set("Question "+str(questionNum))
aText.set(answer1[questionNum])
bText.set(answer2[questionNum])
cText.set(answer3[questionNum])
dText.set(answer4[questionNum])
questionVar.set(questions[questionNum])
except IndexError:
print("No more questions")
Label(menu,text = "AS Maths Chess",font = ("Arial",37)).pack(pady = 20)
Button(menu,text = "Play",background = "black",foreground = "white",font = ("Arial",20),command = play).pack(ipadx = 80,ipady = 20, pady = 10)
Button(menu,text = "Quit",font = ("Arial",20),command = Quit).pack(ipadx = 80,ipady = 20, pady = 10)
Unicode has superscript numerals, arithmetic operators, and some letters in the BMP, which is supported by tcl/tk. See Wikipedia. Within those constraints, and given a supporting font, the answer is yes. On Windows, running from IDLE, the following works nicely and looks nice, though I would want the tk font larger to see the superscript easily with my eyes.
import tkinter as tk
root = tk.Tk()
# "4x^4 + 3x^1/2"
t1 = "4x\u2074 + 3x\u207b\u00b2" # \u excapes, if needed
t2 = "4x⁴ + 3x⁻²"
label = tk.Label(root, text=t2)
label.pack()
(Python 3.3) With no formal instruction, I am trying to advance my very basic knowledge of Python into Tkinter. Below is a program I am trying to write. I have two problems:
1 - When I run this, both radio buttons are active until I click one. Not a huge deal, but it annoys me.
2 - I can't seem to get the .get() method to pull the data entered in the Entry box from the data_window function to the check_data function. As my program eludes, the next step after it passes the check data function will be to send it on to the formatEntry function, which is not written yet. But until I figure this put, that obviously won't work either.
I have a functional version of this without using TKinter and I am trying to adapt that knowledge into this for the purpose of learning. So please feel free to point out any other problems you see, just please keep the explanations very basic for a newb! Thanks
from tkinter import *
import os, shelve
food_entry = None
# Opens a new window for entering food items
def data_window():
global food_entry
new_window_entry = Tk()
new_window_entry.title('Data Entry Window')
Label(new_window_entry, text = 'Enter the food items you have eaten below, separated by commas:').grid(sticky = W, columnspan = 2)
Label(new_window_entry, text = '(i.e. Apple, Eggs, Ground Beef)').grid(sticky = W, columnspan = 2)
food_entry = Text(new_window_entry, width = 55, height = 2, wrap = WORD)
food_entry.grid(sticky = W, columnspan = 2)
#food_entry = Entry(new_window_entry)
Label(new_window_entry, text = 'Within two hours after eating, did you experience any of the following symptoms:').grid(sticky = W, columnspan = 2)
Label(new_window_entry, justify = LEFT, wraplength = 450, text = 'bloating, diarrhea, nausea, vomiting, irritable bowel, skin rashes, fatigue, joint pain, dark circles under the eyes, night sweats, or tingling or swelling of the face, fingers, feet or other extemities?').grid(sticky = W, columnspan = 2)
inflam = StringVar(master = new_window_entry)
Radiobutton(new_window_entry, text = 'Yes', variable = inflam, value = 'y').grid(row = 9, column = 0, sticky = E)
Radiobutton(new_window_entry, text = 'No', variable = inflam, value = 'n').grid(row = 9, column = 1, sticky = W)
Button(new_window_entry, text = 'Submit', command = check_data).grid(row = 10, column = 0, sticky = W + E)
Button(new_window_entry, text = 'Cancel', command = new_window_entry.destroy).grid(row = 10, column = 1, sticky = W + E)
#Check to ensure all fields have been entered
#Convert entry into formatted list
new_window_entry.mainloop()
def check_data():
global food_entry
print(food_entry.get(1.0, END))
if food_entry.get(1.0, END) == None:
print('Nothing Entered')
# tkMessageBox.showwarning(message = 'Please complete all fields of the form.')
else:
print('Next Function')
# formatEntry()
root = Tk()
root.title('')
Label(root, text = 'Food Tracker v3.0').grid(columnspan = 2)
Button(root, text = 'Enter Data', command = data_window).grid(row = 1, column = 0, sticky = W)
Button(root, text = 'View Data', command = view_window).grid(row = 1, column = 1, sticky = E)
First of all you defined food_entry twice, and the second time you never did anything with it (food_entry = Entry(new_window_entry)). You'll need to remove that 2nd definition.
Next, this assigns what grid() returns to food_entry, which is None
food_entry = Text(new_window_entry, width = 55, height = 2, wrap = WORD).grid(sticky = W, columnspan = 2)
So instead you'll need to grid() on a separate line. This keeps the Text() object assigned to food_entry as you intended:
food_entry = Text(new_window_entry, width = 55, height = 2, wrap = WORD)
food_entry.grid(sticky = W, columnspan = 2)
Finally, when accessing a Text() with get() you need to specifiy the start and ending points that you're trying to obtain:
...
print(food_entry.get(1.0, END))
if food_entry.get(1.0, END) == None:
....
Edit: One last thing to cover your question about the Radiobutton() displaying as selected initially, you can correct this by explicitly declaring the master of your StringVar():
inflam = StringVar(master = new_window_entry)
Edit 2: For your if / else statement not working:
if food_entry.get(1.0, END) == None:
This is checking to see if the string in the Text is None, which it's not, it's actually an empty string, so we need to check it accordingly:
if food_entry.get(1.0, END).strip() == '': # Use .strip() to remove spaces and newlines
Here's a complete code sample:
from tkinter import *
import os, shelve
food_entry = None
# Opens a new window for entering food items
def data_window():
global food_entry
new_window_entry = Toplevel() # Change to Toplevel (a popup) instead of a new Tk instance
new_window_entry.title('Data Entry Window')
Label(new_window_entry, text = 'Enter the food items you have eaten below, separated by commas:').grid(sticky = W, columnspan = 2)
Label(new_window_entry, text = '(i.e. Apple, Eggs, Ground Beef)').grid(sticky = W, columnspan = 2)
food_entry = Text(new_window_entry, width = 55, height = 2, wrap = WORD)
food_entry.grid(sticky = W, columnspan = 2)
Label(new_window_entry, text = 'Within two hours after eating, did you experience any of the following symptoms:').grid(sticky = W, columnspan = 2)
Label(new_window_entry, justify = LEFT, wraplength = 450, text = 'bloating, diarrhea, nausea, vomiting, irritable bowel, skin rashes, fatigue, joint pain, dark circles under the eyes, night sweats, or tingling or swelling of the face, fingers, feet or other extemities?').grid(sticky = W, columnspan = 2)
Radiobutton(new_window_entry, text = 'Yes', variable = inflam, value = 'y').grid(row = 9, column = 0, sticky = E)
Radiobutton(new_window_entry, text = 'No', variable = inflam, value = 'n').grid(row = 9, column = 1, sticky = W)
Button(new_window_entry, text = 'Submit', command = check_data).grid(row = 10, column = 0, sticky = W + E)
Button(new_window_entry, text = 'Cancel', command = new_window_entry.destroy).grid(row = 10, column = 1, sticky = W + E)
#new_window_entry.mainloop() No need for this, the mainloop is already running
def check_data():
global food_entry
print(food_entry.get(1.0, END))
if food_entry.get(1.0, END).strip() == '':
print('Nothing Entered')
else:
print('Next Function')
root = Tk()
inflam = StringVar() # move inflam init to a broader scope so that the buttons don't but
inflam.set('n') # initialize it as 'n'
root.title('')
Label(root, text = 'Food Tracker v3.0').grid(columnspan = 2)
Button(root, text = 'Enter Data', command = data_window).grid(row = 1, column = 0, sticky = W)
#Button(root, text = 'View Data', command = view_window).grid(row = 1, column = 1, sticky = E)
root.mainloop()
The purpose of this post is to determine the error within the code, I have spent countless hours trying to alter the code to see what the error is. I am trying to add a employee to a database through a python GUI (tkinter). Currently it is only inserting " " information, this is checked within our the def delete with a print statement. A similar problem I am having with def delete however the information in the tuple is not displaying in a listBox. Does anyone have a solution to why these faults are occurring?
def addEmp():
top = Toplevel()
top.title("Add Employee")
top.geometry("470x385")
app = Frame(top)
app.grid()
firstName = StringVar()
lastName = StringVar()
address = StringVar()
payRate = StringVar()
inUnion = StringVar()
paymentMethod = StringVar()
grp1 = StringVar()
firstNameLabel = Label (app, text = "First Name:", font = 15)
firstNameLabel.grid(row = 0, column = 0)
firstNameEntry = Entry (app, text = "", textvariable = firstName)
firstNameEntry.grid(row = 0, column = 1)
surNameLabel = Label (app, text = "Surname:", font = 15)
surNameLabel.grid(row = 1, column = 0)
lastNameEntry= Entry (app, text = "", textvariable = lastName)
lastNameEntry.grid(row = 1, column = 1)
addressLabel = Label (app, text = "Address:", font = 15)
addressLabel.grid(row = 2, column = 0)
addressEntry = Entry (app, text = "", textvariable = address)
addressEntry.grid(row = 2, column = 1)
payRateLabel = Label (app, text = "Pay Rate Hourly:", font = 15)
payRateLabel.grid(row = 3, column = 0)
payRateEntry = Entry (app, text = "", textvariable = payRate)
payRateEntry.grid(row = 3, column = 1)
salaryLabel = Label (app, text = "Pay Rate Monthly:", font = 15)
salaryLabel.grid(row = 4, column = 0)
salaryEntry = Entry (app, text = "")
salaryEntry.grid(row = 4, column = 1)
payTypeLabel = Label (app, text = "Work Type:", font = 15)
payTypeLabel.grid(row = 5, column = 0)
radio1 = Radiobutton(app, text = "Full Time (Monthly Salary)", value = 'Monthly', variable = grp1)
radio1.grid(row = 6, column = 1)
radio2 = Radiobutton(app, text = "Part Time (Hourly Pay per Week)", value = 'Weekly', variable = grp1)
radio2.grid(row = 7, column = 1)
radio3 = Radiobutton(app, text = "Commission", value = 'Commission', variable = grp1)
radio3.grid(row = 8, column = 1)
paymentOptionsLabel = Label (app, text = "Payment Option:", font = 15)
paymentOptionsLabel.grid(row = 9, column = 0)
radio4 = Radiobutton(app, text = "Mail to current address", value = "Mail", variable = paymentMethod)
radio4.grid(row = 10, column = 1)
radio5 = Radiobutton(app, text = "Held by Paymaster", value = "Hold", variable = paymentMethod)
radio5.grid(row = 11, column = 1)
radio6 = Radiobutton(app, text = "Directly Deposit into bank account", value = "Bank", variable = paymentMethod)
radio6.grid(row = 12, column = 1)
unionLabel = Label (app, text = "Union:", font = 15)
unionLabel.grid(row = 13, column = 0)
radio1union = Radiobutton(app, text = "Yes", value = '1', variable = inUnion)
radio1union.grid(row = 14, column = 1)
radio2union = Radiobutton(app, text = "No", value = '0', variable = inUnion)
radio2union.grid(row = 15, column = 1)
submitButton = Button (app, command = addEmpSubmit, text = "Submit", font = 15)
submitButton.grid(row = 20, column = 3)
def addEmpSubmit():
c.execute("INSERT INTO employees (first_name, last_name, address, in_union, pay_type, payment_method) VALUES (?, ?, ?, ?, ?, ?)",
(str(firstName), str(lastName), str(address), str(inUnion), str(payType), str(paymentMethod)))
connection.commit()
if payType == "Weekly":
c.execute("UPDATE employees SET pay_rate=? WHERE employee_id=?", (payRate, c.lastrowid))
connection.commit()
elif payType == "Monthly":
c.execute("UPDATE employees SET monthly_salary=? WHERE employee_id=?", (monthlySalary, c.lastrowid))
connection.commit()
elif payType == "Commission":
c.execute("UPDATE employees SET monthly_salary=?, commission_rate=? WHERE employee_id=?",
(monthlySalary, commissionRate, c.lastrowid))
connection.commit()
def deleteEmp():
top = Toplevel()
top.title("Delete Employee")
top.geometry("470x385")
deleteList = Listbox(app)
deleteList.grid(row = 0, column = 0)
listItem = ""
c.execute("SELECT * FROM employees")
allEmp = c.fetchall()
for line in allEmp:
for item in line:
print(str(item))
listItem += str(item)
deleteList.insert(END, listItem)
connection.commit()
empIDLabel = Label (app, text = "Please select an Emp ID:", font = 15)
empIDLabel.grid(row = 1, column = 0)
empIDEntry = Entry (app, text = "")
empIDEntry.grid(row = 2, column = 0)
deleteButton = Button (app, text = "Delete", font = 15)
deleteButton.grid(row = 2, column = 1)
Read properly the documentation on ControlVariables / StringVar.
The values you provide for INSERT INTO - queries are not the values of the entry widgets.
>>> name=tk.StringVar()
>>> name.set("First Name")
>>> name
<Tkinter.StringVar instance at 0x01EB4CB0>
>>> str(name)
'PY_VAR0'
>>> name
<Tkinter.StringVar instance at 0x01EB4CB0>
>>> name.get()
'First Name'
Please make sure you post only code samples that can reproduce your error on (at least) your system. As for this reason it is very hard to reproduce the issues you have got.
Split your code up and debug it in smaller slices. Check the different components on their own (e.g. first the sql part with some dummy data but using variables, StringVars, etc.).
Do you receive any error messages? If so, please add them to your post so that we can see if you are struggling at a certain point. Something like - "my code is not working - why?" is hard to analyze if even possible with correct information.
I need to know how to implement the selected radio button into my calculations. Thanks for any and all help! I'm really not positive what the problem is, my only quest really comes from the "def selection" part. I just don't know what to do there
from Tkinter import *
class App(Tk):
def __init__(self):
Tk.__init__(self)
self.headerFont = ("Times", "16", "italic")
self.title("Restaurant Tipper")
self.addOrigBill()
self.addChooseOne()
self.addPercTip()
self.addRateTip()
self.addOutput()
def addOrigBill(self):
Label(self, text = "Bill Amount",
font = self.headerFont).grid(columnspan = 1)
self.txtBillAmount = Entry(self)
self.txtBillAmount.grid(row = 1, column = 1)
self.txtBillAmount.insert(0,"100.00")
def addChooseOne(self):
Label(self, text = "Pick ONE! Choose your % of Tip or Rate your experience",
font = self.headerFont).grid(row = 2, column = 1)
def addPercTip(self):
Label(self, text = "% of Tip",
font = self.headerFont).grid(row = 3, column = 0)
self.radPercTip1 = Radiobutton(self, text = "15%",
variable = self.percVar, value = .15, command = self.selected)
self.radPercTip2 = Radiobutton(self, text = "17%",
variable = self.percVar, value = .17, command = self.selected)
self.radPercTip3 = Radiobutton(self, text = "20%",
variable = self.percVar, value = .20, command = self.selected)
self.radPercTip1.grid(row = 4, column = 0)
self.radPercTip2.grid(row = 5, column = 0)
self.radPercTip3.grid(row = 6, column = 0)
def selected(self):
float(self.percVar.get())
def addRateTip(self):
Label(self, text = "Tip by rating").grid(row = 3, column = 3)
Label(self, text = "1 being the worst").grid(row = 4, column = 3)
Label(self, text = "10 being the best").grid(row = 5, column = 3)
Label(self, text = "Experience").grid(row = 6, column = 2)
self.txtExperience = Entry(self)
self.txtExperience.grid(row = 6, column = 3)
def addOutput(self):
self.btnCalc = Button(self, text = "Calculate Tip")
self.btnCalc.grid(row = 7, columnspan = 2)
self.btnCalc["command"] = self.calculate
Label(self, text = "Tip").grid(row = 8, column = 1)
self.lblTip = Label(self, bg = "#ffffff", anchor = "w", relief = "ridge")
self.lblTip.grid(row = 8, column = 2, sticky = "we")
Label(self, text = "Total Bill").grid(row = 9, column = 1)
self.lblTotalBill = Label(self, bg = "#ffffff", anchor = "w", relief = "ridge")
self.lblTotalBill.grid(row = 9, column = 2, sticky = "we")
def calculate(self):
bill = float(self.txtBillAmount.get())
percTip = self.percVar
rateTip = int(self.addRateTip.get())
tip = bill * percTip
self.lblTip["text"] = "%.2f" % tip
totalBill = tip + bill
self.lblTotalBill["text"] = "%.2f" % totalBill
if rateTip <= 2:
percTip = .10
elif 3 <= rateTip <= 4:
percTip = .12
elif 5 <= rateTip <= 6:
percTip = .15
elif 7 <= rateTip <= 8:
percTip = .17
elif 9 <= rateTip <= 10:
percTip = .20
else:
self.lblTotalBill["text"] = "Something is wrong"
def main():
app = App()
app.mainloop()
if __name__ == "__main__":
main()
There is no self.percVar in your code. As #wastl said, you need to initialize it.
To do that, you need to use one of the variable classes. Since you are using float type, DoubleVar() would be the best.
def addPercTip(self):
self.percVar = DoubleVar() #this line should be added in your method
Label(self, text = "% of Tip",
font = self.headerFont).grid(row = 3, column = 0)
def selected(self):
print (type(self.percVar.get()))
#which is float, without converting explicitly because of DoubleVar()
print (self.percVar.get())
#this will print what you click
You forgot to intialize the self.percVar variable
Add self.percVar = 0 as the first line of the addPercTip method. That should fix your error.
BTW: For future questions the best thing is to include the error message you get and EXACTLY describe what part of the programm causes what kind of trouble for you