Tip calculator - syntax error - python

Hello guys im new to programming relatively, but all the same im trying to use a GUI interface to build a tip calculator. nothing big, nothing relatively hard, but im running into errors. for some reason my Python wont show the errors. it just goes to the shell, says SyntaxError: and then quits back to the script. it used to show the errors but i dont know whats wrong... anyways if you guys could help me troubleshoot this id greatly appreciate it..
`
# A tip calculator
# A tip calculator using a GUI interface
# Austin Howard Aug - 13 - 2014
from tkinter import *
#Creating buttons.
class Calculator(Frame):
""" A GUI tip calculator."""
def __init__(self, master):
Frame.__init__(self, master)
self.grid()
self.creating_buttons()
def creating_buttons(self):
"""This list includes Entry fields, which the user will use to define
several objects such as Bill, and how many people are paying on that bill."""
#Create an entry field button for how much the bill total is.
#Create a label
bill_lbl = Label(self,
text = "Bill: ")
bill_lbl.grid(row = 1,
column = 0,
columnspan = 1,
sticky = W)
#Create an Entry field.
bill_ent = Entry(self)
bill_ent.grid(row = 1,
column = 1,
sticky = W)
#Create a Button for how many people will be paying on the bill
#Create label
people_paying_lbl = Label(self,
text = "How many people are paying on this bill?: ")
people_paying_lbl.grid(row = 2,
column = 0,
columnspan = 1,
sticky = W)
#Create an entry field
people_paying_ent = Entry(self)
people_paying_ent.grid(row = 2,
column = 1,
sticky = W)
#Create a text box to display the totals in
bill_total_txt = Text(self,
width = 40,
height = 40,
wrap = WORD)
bill_total_txt.grid(row = 3,
column = 0,
columnspan = 2,
sticky = W)
#Create a Submit button
submit = Button(self,
text = "Submit",
command = self.total)
submit.grid(row = 4,
column = 0,
sticky = W)
def total(self):
""" Takes the values from Bill, and # of people to get the amount that will be
displayed in the text box."""
TAX = .15
bill = float(bill_ent)
people = people_paying_ent
Total = ("The tip is: $", TAX * bill, "\nThe total for the bill is: $",
TAX * bill + bill,
"divided among the people paying equally is: $",
TAX * bill + bill / people "per, person.")
bill_total_txt.delete(0.0, END)
bill_total_txt.insert(0.0, Total)
#Starting the Program
root = Tk()
root.title("Tip Calculator")
app = Calculator(root)
root.mainloop()
`

You have an error on line 68:
Replace
TAX * bill + bill / people "per, person.")
with
TAX * bill + bill / people, "per, person.")
Also make sure you remove the backtick after root.mainloop()

Your way of getting the input from the Entry boxes is wrong. You should bind a StringVariable to them, to later be able to get what the user typed:
self.billvar = StringVar()
bill_ent = Entry(self, textvariable = self.billvar)
And the same for the number of people box.
Then in your total function you can read the values by using self.billvar.get(). You can convert this to a float using float(self.billvar.get()). However, when this fails (the user typed in something that can not be converted to a float) you probably want to tell them instead of having the program throwing an error. So you should use something like:
try:
convert input
except:
what to do if it fails, tell the user?
else:
what to do if it did not fail, so do the calculations
Your program then becomes something like this (I made comments with ##):
# A tip calculator
# A tip calculator using a GUI interface
# Austin Howard Aug - 13 - 2014
from tkinter import *
#Creating buttons.
class Calculator(Frame):
""" A GUI tip calculator."""
def __init__(self, master):
Frame.__init__(self, master)
self.grid()
self.creating_buttons()
def creating_buttons(self):
"""This list includes Entry fields, which the user will use to define
several objects such as Bill, and how many people are paying on that bill."""
#Create an entry field button for how much the bill total is.
#Create a label
bill_lbl = Label(self,
text = "Bill: ")
bill_lbl.grid(row = 1,
column = 0,
columnspan = 1,
sticky = W)
#Create an Entry field.
## Create a StringVar and link it to the entry box
self.billvar = StringVar()
bill_ent = Entry(self, textvariable = self.billvar)
bill_ent.grid(row = 1,
column = 1,
sticky = W)
#Create a Button for how many people will be paying on the bill
#Create label
people_paying_lbl = Label(self,
text = "How many people are paying on this bill?: ")
people_paying_lbl.grid(row = 2,
column = 0,
columnspan = 1,
sticky = W)
#Create an entry field
## Create a StringVar and link it to the entry box
self.pplvar = StringVar()
people_paying_ent = Entry(self, textvariable = self.pplvar)
people_paying_ent.grid(row = 2,
column = 1,
sticky = W)
#Create a text box to display the totals in
## This had to be self.bill_total_txt, to be able to put text in it from the total function
self.bill_total_txt = Text(self,
height = 10,
width = 40,
wrap = WORD)
self.bill_total_txt.grid(row = 3,
column = 0,
columnspan = 2,
sticky = W)
#Create a Submit button
submit = Button(self,
text = "Submit",
command = self.total)
submit.grid(row = 4,
column = 0,
sticky = W)
def total(self):
""" Takes the values from Bill, and # of people to get the amount that will be
displayed in the text box."""
TAX = .15
## Try to convert the bill to a float and the number of people to an integer
try:
bill = float(self.billvar.get())
people = int(self.pplvar.get())
## If something goes wrong tell the user the input is invalid
except:
self.bill_total_txt.delete(0.0, END)
self.bill_total_txt.insert(0.0, 'Invalid input')
## If the conversion was possible, calculate the tip, the total amount and the amout per person and format them as a string with two decimals
## Then create the complete message as a list and join it togeather when writing it to the textbox
else:
tip = "%.2f" % (TAX * bill)
tot = "%.2f" % (TAX * bill + bill)
tot_pp = "%.2f" % ((TAX * bill + bill) / people)
Total = ["The tip is: $", tip,
"\nThe total for the bill is: $",
tot,
" divided among the people paying equally is: $",
tot_pp,
" per person."]
self.bill_total_txt.delete(0.0, END)
self.bill_total_txt.insert(0.0, ''.join(Total))
#Starting the Program
root = Tk()
root.title("Tip Calculator")
app = Calculator(root)
root.mainloop()

Related

Python tkinter calculate student status

I am working on a python Tkinter assignment in which an input box accepts user input and then displays the GPA and student status. Im pretty sure I have this setup wrong and am looking for advice on how to use an If statement to determine student status. Should everything fall under the getStudentStatus function or is it better to have two functions?
import math
from tkinter import *
#calculate student status
def getStudentStatus():
data = float(inputGPA.get())
floatedGPA = (data)
#Print student status
label2 = Label(GPA, text = 'Your GPA is:' ' %.2f' % floatedGPA).grid(row = 3, column = 0)
label3 = Label(GPA, getStanding).grid(row = 4, column = 0)
return
def getStanding():
#Get academic Status
if(data>=3.5):
return("This student is on the Deans List")
elif(data>=2.0):
return("This student is on Acedmic Probation")
else:
return("This student has Regular Standing")
#define window
GPA = Tk()
GPA.title("GPA Tool")
GPA.geometry("200x200")
#define variables
inputGPA = StringVar()
#label for text box
label1 = Label(GPA, text="Enter your GPA: ").grid(row = 0, column = 0)
#entry text box
entry1 = Entry(GPA, textvariable = inputGPA).grid(row = 1, column = 0)
#submit button
button1 = Button(GPA, text="Submit", command=getStudentStatus).grid(row = 2, column = 0)
GPA.mainloop()
To avoid that a new label is created on every button press, you could create an empty label outside of the function.
To assign the label object to a variable, split the creation and the placement.
In the function you could configure the label and add the wanted output.
Additionally you need to pass the float to the second function so that the comparison operators have a value to compare.
import math
from tkinter import *
#calculate student status
def getStudentStatus():
data = float(inputGPA.get())
floatedGPA = (data)
#Print student status
label2.configure(text = 'Your GPA is:' ' %.2f' % floatedGPA)
label3.configure(text = getStanding(floatedGPA))
def getStanding(data):
#Get academic Status
if(data>=3.5):
return("This student is on the Deans List")
elif(data>=2.0):
return("This student is on Acedmic Probation")
else:
return("This student has Regular Standing")
#define window
GPA = Tk()
GPA.title("GPA Tool")
GPA.geometry("200x200")
#define variables
inputGPA = StringVar()
#label for text box
label1 = Label(GPA, text="Enter your GPA: ").grid(row = 0, column = 0)
#entry text box
entry1 = Entry(GPA, textvariable = inputGPA).grid(row = 1, column = 0)
# create empty labels
label2 = Label(GPA, text = '')
label3 = Label(GPA, text='')
# place empty labels
label2.grid(row = 3, column = 0)
label3.grid(row = 4, column = 0)
#submit button
button1 = Button(GPA, text="Submit", command=getStudentStatus).grid(row = 2, column = 0)
GPA.mainloop()

How to save an entry in Tkinter to later use in a calculation, then print the answer inside the Tkinter window

I am trying to make a program which calculates 3-4 values using some user inputted values
I have tried making a function which saves the entries into variables, and making the variables global but that didn't work
from tkinter import *
from math import *
root = Tk()
label1 = Label(root, text = "Enter value for length ")
label1.grid(columnspan = 2, sticky = "W")
length = Entry(root)
length.grid(row = 0, column = 2)
label2 = Label(root, text = "Enter value for volume ")
label2.grid(columnspan = 2, sticky = "W")
volume = Entry(root)
volume.grid(row = 1, column = 2)
label3 = Label(root, text = "Enter value for the thickness of the cylinder ")
label3.grid(columnspan = 2, sticky = "W")
thickness = Entry(root)
thickness.grid(row = 2, column = 2)
label4 = Label(root, text = "Enter value for starting temperature ")
label4.grid(columnspan = 2, sticky = "W")
st_T = Entry(root)
st_T.grid(row = 3, column = 2)
label5 = Label(root, text = "Enter value for finishing temperature ")
label5.grid(columnspan = 2, sticky = "W")
end_T = Entry(root)
end_T.grid(row = 4, column = 2)
def save():
v = volume.get()
l = length.get()
w = thickness.get()
t0 = st_T.get()
t1 = end_T.get()
global values
values = [v, l, w, t1, t0]
Button(root, text = "Submit", command = save).grid(row = 6, column = 0)
root.mainloop()
I know the current code isn't very pretty and is very inefficient but the error keeps saying that v is not defined
You might consider declaring a variable, or a an instance of a context object (that you will define) at global scope to store your user inputs.
Then you will be able to read the user inputs later in another function.
Do not forget to use the keyword 'global' before modifying the global object in a different scope (like in a function). Have a look here : https://www.geeksforgeeks.org/global-keyword-in-python/
By example you could declare your global object/variable/whatever you need, along with your root Tkinter object.

How to make entries from an entry widget interact with each other

I'm trying to make a program which would allow a user to enter a currency and a US Dollar amount, and have the program run the conversion, and of course show the result to the user. I'm using tkinter and have a gui pop up where the user can enter in values, and as of now it just prints whatever the user entered on the IDLE window (to test whether what I have would do anything).
from tkinter import *
from math import *
fields = 'Dollars' , 'Currency'
def fetch(entries):
for entry in entries:
field = entry[0]
text = entry[1].get()
print('%s: "%s"' % (field, text))
def makeform(root, fields):
entries = []
for field in fields:
row = Frame(root)
lab = Label(row, width = 15, text = field, anchor = 'w')
ent = Entry(row)
row.pack(side = TOP, fill = X, padx=5, pady = 5)
lab.pack(side = LEFT)
ent.pack(side = RIGHT, expand = YES, fill = X)
entries.append((field, ent))
return entries
if __name__ == '__main__':
root = Tk()
ents = makeform(root, fields)
root.bind('<Return>', (lambda event, e = ents: fetch(e)))
b1 = Button(root, text = 'Show', command = (lambda e=ents: fetch(e)))
b1.pack(side = LEFT, padx = 5, pady =5)
b2 = Button(root, text = 'Quit', command=root.quit)
b2.pack(side = LEFT, padx = 5, pady = 5)
root.mainloop()
The only code that I have used for converting currency is something like this:
def convert():
option = input("Please enter what you would like to convert $ to; Yen, Euros, or Pesos: ")
dollars = eval(input("Please enter the dollar amount you wish to convert: "))
if dollars < 0:
print("You must enter a value greater than 0.")
convert()
elif option == "Yen":
print("The amount of Yen you have is: ", dollars * 106.84)
elif option == "Euros":
print("The amount of Euros you have is: ", dollars * 0.77)
elif option == "Pesos":
print("The amount of Pesos you have is: ", dollars * 13.38)
I've looked across numerous websites, but I have not found any useful information anywhere on how to incorporate the two together. If anyone could help me understand what I need to do, it would be greatly appreciated.
Rephrasing the question: How to update the value of on Entry depending on the value of another Entry?
This seems to require code like:
value=eval(entryDollar.get())
entryCurrency.delete(0,END)
entryCurrency.insert(0,repr(value*exchangeRate))
In your current bindings with Show, <Return> it is unclear what direction you want to convert; a direction indicator might help.

How do I make a GUI using the model/view/controller method?

I need to understand the concept behind the model/view/controller method and how to write a GUI that way. Here's just a really basic, simple GUI. Can someone explain to me how to rewrite this code using MVC?
from tkinter import *
class Application(Frame):
""" GUI application that creates a story based on user input. """
def __init__(self, master):
""" Initialize Frame. """
super(Application, self).__init__(master)
self.grid()
self.create_widgets()
def create_widgets(self):
""" Create widgets to get story information and to display story. """
# create instruction label
Label(self,
text = "Enter information for a new story"
).grid(row = 0, column = 0, columnspan = 2, sticky = W)
# create a label and text entry for the name of a person
Label(self,
text = "Person: "
).grid(row = 1, column = 0, sticky = W)
self.person_ent = Entry(self)
self.person_ent.grid(row = 1, column = 1, sticky = W)
# create a label and text entry for a plural noun
Label(self,
text = "Plural Noun:"
).grid(row = 2, column = 0, sticky = W)
self.noun_ent = Entry(self)
self.noun_ent.grid(row = 2, column = 1, sticky = W)
# create a label and text entry for a verb
Label(self,
text = "Verb:"
).grid(row = 3, column = 0, sticky = W)
self.verb_ent = Entry(self)
self.verb_ent.grid(row = 3, column = 1, sticky = W)
# create a label for adjectives check buttons
Label(self,
text = "Adjective(s):"
).grid(row = 4, column = 0, sticky = W)
# create itchy check button
self.is_itchy = BooleanVar()
Checkbutton(self,
text = "itchy",
variable = self.is_itchy
).grid(row = 4, column = 1, sticky = W)
# create joyous check button
self.is_joyous = BooleanVar()
Checkbutton(self,
text = "joyous",
variable = self.is_joyous
).grid(row = 4, column = 2, sticky = W)
# create electric check button
self.is_electric = BooleanVar()
Checkbutton(self,
text = "electric",
variable = self.is_electric
).grid(row = 4, column = 3, sticky = W)
# create a label for body parts radio buttons
Label(self,
text = "Body Part:"
).grid(row = 5, column = 0, sticky = W)
# create variable for single, body part
self.body_part = StringVar()
self.body_part.set(None)
# create body part radio buttons
body_parts = ["bellybutton", "big toe", "medulla oblongata"]
column = 1
for part in body_parts:
Radiobutton(self,
text = part,
variable = self.body_part,
value = part
).grid(row = 5, column = column, sticky = W)
column += 1
# create a submit button
Button(self,
text = "Click for story",
command = self.tell_story
).grid(row = 6, column = 0, sticky = W)
self.story_txt = Text(self, width = 75, height = 10, wrap = WORD)
self.story_txt.grid(row = 7, column = 0, columnspan = 4)
def tell_story(self):
""" Fill text box with new story based on user input. """
# get values from the GUI
person = self.person_ent.get()
noun = self.noun_ent.get()
verb = self.verb_ent.get()
adjectives = ""
if self.is_itchy.get():
adjectives += "itchy, "
if self.is_joyous.get():
adjectives += "joyous, "
if self.is_electric.get():
adjectives += "electric, "
body_part = self.body_part.get()
# create the story
story = "The famous explorer "
story += person
story += " had nearly given up a life-long quest to find The Lost City of "
story += noun.title()
story += " when one day, the "
story += noun
story += " found "
story += person + ". "
story += "A strong, "
story += adjectives
story += "peculiar feeling overwhelmed the explorer. "
story += "After all this time, the quest was finally over. A tear came to "
story += person + "'s "
story += body_part + ". "
story += "And then, the "
story += noun
story += " promptly devoured "
story += person + ". "
story += "The moral of the story? Be careful what you "
story += verb
story += " for."
# display the story
self.story_txt.delete(0.0, END)
self.story_txt.insert(0.0, story)
# main
def main():
root = Tk()
root.title("Mad Lib")
app = Application(root)
root.mainloop()
main()
ToyMVC "Toy MVC (Model View Controller) design" in the Tkinter docs is probably what you're looking for. I would personally design things a bit differently, but it mostly makes sense.
The key is separating out the model and view, and the controller is then all the bits that connect up a model and a view.
So, instead of having an Application with everything in it, you'd have these classes:
StoryModel: A model of a story.
StoryView: A window or other widget that you stick inside the frame—although in Tk, you can just as easily make it the frame itself.
StoryController: A class that, given a StoryModel and a StoryView, will tell its StoryView to create the appropriate widgets to display that story, and will then monitor both Model and View for changed and transmit them from one to the other.
Given that, you can create a simple Application that creates one StoryModel, one StoryView, one frame window to put the View in, and one StoryController to connect up the model and view.
For example, StoryModel could look like this:
class StoryModel(object):
body_parts = ['bellybutton', 'big toe', 'medulla oblongato']
def __init__(self):
self.person = ObservableStr('')
# ...
self.is_itchy = ObservableBool(False)
# ...
def tell(self):
story = "The famous explorer "
# ...
return story
And then you can get fancy and create an AlternateStoryView that displays the same information in a different way, and change the Application to create one of each view, and a controller for each, attached to the same model. For example, you might create a view that didn't use a grid, and instead automatically laid things out:
class AlternateStoryView(Frame):
def __init__(self, master):
super(StoryView, self).__init__(master)
def add_label(label):
label = Label(self, text=label)
label.pack()
return label
If you know about the trace method, you may notice that an Observable isn't really any different than using Tkinter.StringVar, etc. But the advantage (besides not having the clunky syntax of trace…) is that there's nothing Tkinter-specific about the model this way.
So, you can create a GtkStoryView or a CursesStoryView, without changing any of the code in the Model and Controller. (This doesn't quite work with ToyMVC, because things like addButton.config(command=self.addMoney) won't exactly translate to Gtk+ or curses unless you built a big Tk emulation layer… but you don't have to make that mistake in your design.)
Also, note that using Observable wrappers around all of your model variables is definitely not the only way to hook up a controller, or even necessarily the most Pythonic.
If you want to start/learn MVC web development using python language i suggest to get started with Django Framework

Debugging RadioButtons program in Python

I wrote a simple program importing Tkinter just to play with Radio Buttons. I find that I'm getting errors in very, very weird places.
from Tkinter import *
class Application (Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.grid()
self.create_widgets()
def create_widgets(self):
Label(self, text = "Select the last book you read.").grid (row = 0, column = 0, sticky = W)
self.choice = StringVar()
Radiobutton (self,text = "Nausea by Jean-Paul Sartre",variable = self.choice,
value = "Wake up. This is a dream. This is all only a test of the emergency broadcasting system.",
command = self.update_text).grid (row = 2, column = 1, sticky = W)
Radiobutton (self,
text = "Infinite Jest by David Foster Wallace",
variable = self.choice,
value = "Because an adult borne without the volition to choose the thoughts that he thinks, is going to get hosed ;)",
command = self.update_text).grid (row = 3, column = 1, sticky = W)
Radiobutton (self,
text = "Cat's Cradle by Kurt Vonnegut",
variable = self.choice,
value = " \"Here we are, trapped in the amber of the moment. There is no why!\" ",
command = self.update_text.grid (row = 4, column = 1, sticky = W)
self.txt_display = Text (self, width = 40, height = 5, wrap = WORD)
self.txt_display.grid (row = 6, column = 0, sticky = W)
#There is only one choice value - self.choice. That can be "printed."
def update_text(self):
message = self.choice.get()
self.txt_display.delete (0.0, END)
self.txt_display.insert (0.0, message)
# The Main
root = Tk()
root.title ("The Book Critic One")
root.geometry ("400x400")
app = Application (root)
root.mainloop()
I seem to be getting errors in very odd places. One came in the "=" sign in the Label attribution and when I changed it to == when i was playing around, the next one came in the variable part of the RadioButton attributes.
Any help would be greatly appreciated. Won't be able to respond immediately as I have to leave to work in a bit, but if you do spot where the bugs are, please let me know.
There are a lot of things going on here. I'll just point out the few that I've found quickly looking at this.
For your Label you shouldn't have = before your parameters...
Label = (self, text = "Select the last book you read.").grid (row = 0, column = 0, sticky = W)
to:
Label(self, text = "Select the last book you read.").grid (row = 0, column = 0, sticky = W)
Change all instances of RadioButton to Radiobutton as that is the actual name of the class in Tkinter.
choice1, choice2, and choice3 do not exist in Application.
More Stuff:
def create_widgets() is missing the self parameter: def create_widgets(self)
Your update_text() function isn't working because you're referencing self.text_display, I believe you want this to be self.txt_display since that is how you defined it previously.

Categories