Reputation: 311
I was working on a tkinter project. It just a simple restaurant cashier (whatever you call it) project. It's not done yet but I was stuck on a problem.
Here is my code:
from tkinter import *
from tkinter.ttk import Style
# The different type of items that the store is selling
drinks = {}
burgers = {}
french_fries = {}
ice_creams = {}
class Object:
def __init__(self, name, price, type):
self.name = name
self.price = price
self.type = type
exec('{}["{}"] = [{}, {}]'.format(self.type, name, price, self.type))
def return_price(self):
return self.price
def get_price(self, amount):
return self.price * amount
# Creating the object
Object('Coco Cola', 1.50, 'drinks')
Object('Sprite', 1.50, 'drinks')
Object('Apple Juice', 2.50, 'drinks')
Object('Orange juice', 2.50, 'drinks')
Object('Grape Juice', 2.50, 'drinks')
Object('Cheese and Ham', 3.75, 'burgers')
Object('Cheese', 4.00, 'burgers')
Object('Cheese and Fish', 3.50, 'burgers')
Object('All Meat', 5.50, 'burgers')
Object('Waffle Fries', 2.50, 'french_fries')
Object('Chili Cheese Fries', 2.75, 'french_fries')
Object('Polenta Fries', 3.50, 'french_fries')
Object('Potato Wedges', 3.50, 'french_fries')
Object('Strawberry', 3.50, 'ice_creams')
Object('Blueberry', 3.75, 'ice_creams')
Object('Black Berry', 3.00, 'ice_creams')
Object('Vanilla', 3.00, 'ice_creams')
Object('Chocolate', 3.50, 'ice_creams')
# This code is what gives me the result i specified at the bottom of my question
print(drinks)
# All the tkinter stuff
root = Tk()
root.resizable(width=False, height=False)
root.style = Style()
root.style.theme_use('xpnative')
drink, burger, french_fry, ice_cream = StringVar(), StringVar(), StringVar(), StringVar()
drink_amount, burger_amount, french_fry_amount, ice_cream_amount = IntVar(), IntVar(), IntVar(), IntVar()
subtotal, tax, total, change = IntVar(), IntVar(), IntVar(), IntVar()
drink_amount.set(0)
burger_amount.set(0)
french_fry_amount.set(0)
ice_cream_amount.set(0)
Label(root, text='Restaraunt Cashier').grid(row=0, column=1, columnspan=5)
Label(root, text='Drinks:').grid(row=1, sticky=W)
Label(root, text='Burgers:').grid(row=2, sticky=W)
Label(root, text='French Fries:').grid(row=3, sticky=W)
Label(root, text='Ice cream:').grid(row=4, sticky=W)
Label(root, text='Amount:').grid(row=1, column=2, sticky=E)
Label(root, text='Amount:').grid(row=2, column=2, sticky=E)
Label(root, text='Amount:').grid(row=3, column=2, sticky=E)
Label(root, text='Amount:').grid(row=4, column=2, sticky=E)
Label(root, text='Subtotal:').grid(row=1, column=4, sticky=W)
Label(root, text='Tax:').grid(row=2, column=4, sticky=W)
Label(root, text='Total:').grid(row=3, column=4, sticky=W)
Label(root, text='Change:').grid(row=4, column=4, sticky=W)
# Entry types
drink_entry = OptionMenu(root, drink, *drinks)
burger_entry = OptionMenu(root, burger, *drinks)
french_fries_entry = OptionMenu(root, french_fry, *drinks)
ice_cream_entry = OptionMenu(root, ice_cream, *drinks)
# Entry amount
drink_entry_amount = Entry(root, width=50)
burger_entry_amount = Entry(root, width=50)
french_fry_entry_amount = Entry(root, width=50)
ice_cream_entry_amount = Entry(root, width=50)
# Subtotal, tax, total, change, entries
subtotal_entry = Entry(root, width=50)
tax_entry = Entry(root, width=50)
total_entry = Entry(root, width=50)
change_entry = Entry(root, width=50)
# Gridding
drink_entry.grid(row=1, column=1, ipady=5)
burger_entry.grid(row=2, column=1, ipady=5)
french_fries_entry.grid(row=3, column=1, ipady=5)
ice_cream_entry.grid(row=4, column=1, ipady=5)
drink_entry_amount.grid(row=1, column=3, ipady=5)
burger_entry_amount.grid(row=2, column=3, ipady=5)
french_fry_entry_amount.grid(row=3, column=3, ipady=5)
ice_cream_entry_amount.grid(row=4, column=3, ipady=5)
subtotal_entry.grid(row=1, column=5, ipady=5)
tax_entry.grid(row=2, column=5, ipady=5)
total_entry.grid(row=3, column=5, ipady=5)
change_entry.grid(row=4, column=5, ipady=5)
entry_list = [
'drink_entry', 'burger_entry', 'french_fries_entry', 'ice_cream_entry', 'drink_entry_amount', 'burger_entry_amount',
'french_fries_entry_amount', 'ice_cream_entry_amount'
]
item_selected = []
def submit_clicked(event=None):
global item_selected
drink_amount.set(drink_entry_amount.get())
burger_amount.set(burger_entry_amount.get())
french_fry_amount.set(french_fry_entry_amount.get())
ice_cream_amount.set(ice_cream_entry_amount.get())
item_selected.append(drink.get())
item_selected.append(burger.get())
item_selected.append(french_fry.get())
item_selected.append(ice_cream.get())
item_selected = list(filter(None, item_selected))
submit_button = Button(root, text='Submit', command=submit_clicked)
submit_button.grid(row=6, column=1, columnspan=5)
root.grid_rowconfigure(5, minsize=20)
root.mainloop()
I'll walk you through the code:
I think the item_selected here is uneccessary.
So, the problem here is when I run, it give me something like this:
{'Coco Cola': [1.5, {...}], 'Sprite': [1.5, {...}], 'Apple Juice': [2.5, {...}], 'Orange juice': [2.5, {...}], 'Grape Juice': [2.5, {...}]}
What I expected from the code:
{'Coca Cola': [1.5, 'drinks'], 'Sprite': [1.5, 'drinks'], 'Apple Juice': [2.5, 'drinks'], 'Orange juice': [2.5, 'drinks'], 'Grape Juice': [2.5, 'drinks']}
I'm believe my problem does not interfere with the tkinter code, I might be wrong but I just want people pinpoint my mistakes cause I can't right now.
Upvotes: 0
Views: 267
Reputation: 104712
As I think @Aran-Fey diagnosed in the comments, your issue has to do with your exec
call in Object.__init__
, which isn't doing what you expect. When do:
exec('{}["{}"] = [{}, {}]'.format(self.type, name, price, self.type))
with self.type
equal to the name of one of your dictionaries (like "drinks"
), you are running this Python statement:
drinks[...] = [..., drinks]
That is, you're assigning a reference to the dictionary as a part of a value in the dictionary. I suspect you want to that value to include the string "drinks"
instead of a reference to the dictionary named drinks
. For that you'd need {!r}
in the format string.
But better yet, do away with the exec
call entirely! Variable names should not be data. If you have a data item like the string "drinks"
and you want that to let you look up a dictionary, use it as a key in another level of dictionary.
So rather than four top-level variables:
drinks = {}
burgers = {}
french_fries = {}
ice_creams = {}
Make just one (which I've uncreatively named data
, you might come up with a better name):
data = {"drinks": {}, "burgers": {}, "french_fries": {}, "ice_creams": {}}
Then instead of needing exec
, you can just index the dictionary as necessary:
data[self.type][name] = [price, self.type]
There are some other issues in your code as well. It's very weird that you're creating Object
instances exclusively for their side-effects (you throw away each instance immediately after it's created). That could make sense if the constructor inserts the object into a data structure (as for instance, TKinter
types often do). If you only care about side effects, just move the code from Object.__init__
into a top level function and do away with the class!
Several of your Entry
objects appear to be referencing the wrong dictionary: burger_entry = OptionMenu(root, burger, *drinks)
should probably have *burgers
as its last argument (or *data['burgers']
if you change the data structures as I suggested above).
Upvotes: 1