[英]How can I make a tkinter button for loop with different commands that execute functions with different parameters?
I am trying to write a restaurant app that displays all available menu options, and adds the item price to the total after the menu item button is clicked.我正在尝试编写一个显示所有可用菜单选项的餐厅应用程序,并在单击菜单项按钮后将项目价格添加到总数中。 For example, if I click "cheeseburger," 12.99 is added to the total and the label on the bottom is automatically updated.
例如,如果我点击“芝士汉堡”,总数会增加 12.99,并且底部的 label 会自动更新。 Here is my code:
这是我的代码:
import tkinter as tk
from tkinter import ttk
import tkinter.font as font
from restaurantSoftware import restaurantInfo
import time
try:
from ctypes import windll
windll.shcore.SetProcessDpiAwareness(1)
except:
pass
class restaurantSoftware(tk.Tk):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.title("Restaurant Software POS")
self.frames = dict()
container = ttk.Frame(self)
container.grid(padx=60, pady=30, sticky='EW')
self.sideNavMenu = sideNavMenu(container, self, width=200, height=600)
self.sideNavMenu.grid(row=0, column=0)
style = ttk.Style()
for frameClass in (homeFrame, tableManagementFrame, menuFrame, employeeManagementFrame):
frame = frameClass(container, self)
self.frames[frameClass] = frame
style.configure(f'{frame}.TFrame', background='black')
frame.grid(row=0, column=1, sticky='NESW')
self.show_frame(homeFrame)
def show_frame(self, container):
frame = self.frames[container]
frame.tkraise()
class sideNavMenu(ttk.Frame):
def __init__(self, container, controller, **kwargs):
super().__init__(container, **kwargs)
homeButton = ttk.Button(self, text='Home', command=lambda: controller.show_frame(homeFrame))
tablesButton = ttk.Button(self, text='Table Management', command=lambda: controller.show_frame(tableManagementFrame))
menuButton = ttk.Button(self, text='Menu', command=lambda: controller.show_frame(menuFrame))
employeeButton = ttk.Button(self, text='Employee Management', command=lambda: controller.show_frame(employeeManagementFrame))
homeButton.pack(padx=10, pady=25, fill='both')
tablesButton.pack(padx=10, pady=25, fill='both')
menuButton.pack(padx=10, pady=25, fill='both', )
employeeButton.pack(padx=10, pady=25, fill='both')
class homeFrame(ttk.Frame):
def __init__(self, container, controller, **kwargs):
super().__init__(container, **kwargs)
class tableManagementFrame(ttk.Frame):
def __init__(self, container, controller, **kwargs):
super().__init__(container, **kwargs)
class menuFrame(ttk.Frame):
def __init__(self, container, controller, **kwargs):
super().__init__(container, **kwargs)
self.tableTotal = tk.StringVar()
tableNumber = 12
tableList = []
for table in range(0, tableNumber + 1):
tableList.append(f'Table {table}')
self.availableItems = restaurantInfo.readRestaurantInfo('availableItems.csv')
self.itemList = self.availableItems[0]
self.priceList = self.availableItems[1]
self.categoryList = self.availableItems[2]
self.selectedTable = tk.StringVar()
tableSelector = ttk.Combobox(self, textvariable=self.selectedTable, width=50, font=('Segoe UI', 16))
tableSelector['values'] = tableList
tableSelector['state'] = 'readonly'
tableSelector.set('Set Table Number...')
tableSelector.grid(row=0, column=0, columnspan=3, padx=15, pady=15)
COLUMNS = 3
for i, item in enumerate(self.itemList):
lbl = ttk.Button(self, text=item, style='my.TButton', command=self.calculate(self.priceList[i]))
row, column = divmod(i, COLUMNS)
lbl.grid(row=row + 1, column=column, sticky='news', ipadx=25, ipady=25)
self.tableInfoFrame = ttk.Frame(self)
self.tableInfoFrame.grid()
totalLabel = ttk.Label(self.tableInfoFrame, textvariable=self.tableTotal)
totalLabel.pack()
def calculate(self, amount):
total = 0
total += amount
self.tableTotal.set(total)
class employeeManagementFrame(ttk.Frame):
def __init__(self, container, controller, **kwargs):
super().__init__(container, **kwargs)
root = restaurantSoftware()
font.nametofont("TkDefaultFont").configure(size=15)
root.columnconfigure(0, weight=1) # centers the main content as the window is expanded
root.mainloop()
Here is what my program looks like: https://imgur.com/a/rwjqygR这是我的程序的样子: https://imgur.com/a/rwjqygR
Here is the csv that my program reads: https://imgur.com/a/tdDQUPg这是我的程序读取的csv:https://imgur.com/a/tdDQUPg
The main issue is in the following code:主要问题在以下代码中:
lbl = ttk.Button(self, text=item, style='my.TButton', command=self.calculate(self.priceList[i]))
It will execute self.calculate(self.priceList[i])
immediately and assign the result ( None
) to command
option.它将立即执行
self.calculate(self.priceList[i])
并将结果( None
)分配给command
选项。 So when those buttons are clicked, nothing happens.因此,当单击这些按钮时,什么也没有发生。
You need to use lambda with argument with default value instead:您需要使用带有默认值参数的 lambda 代替:
bl = ttk.Button(self, text=item, style='my.TButton', command=lambda price=self.priceList[i]: self.calculate(price))
Also you reset total
every time self.calculate()
is executed:每次执行
self.calculate()
时,您也会重置total
:
def calculate(self, amount):
total = 0 # total is reset here
total += amount
self.tableTotal.set(total)
So self.tableTotal
will only show the price of the item clicked.所以
self.tableTotal
只会显示所点击商品的价格。
Suggest to change self.tableTotal
from StringVar
to DoubleVar
and get the current total from it inside self.calculate()
:建议将
self.tableTotal
从StringVar
更改为DoubleVar
并从中获取当前总数self.calculate()
:
class menuFrame(ttk.Frame):
def __init__(self, container, controller, **kwargs):
super().__init__(container, **kwargs)
self.tableTotal = tk.DoubleVar(value=0.0) # Use DoubleVar instead
...
def calculate(self, amount):
total = self.tableTotal.get() # get current total
total += amount
self.tableTotal.set(round(total,2)) # update total
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.