简体   繁体   English

如何使用执行具有不同参数的功能的不同命令制作 tkinter 按钮循环?

[英]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.tableTotalStringVar更改为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.

相关问题 如何使用 tkinter python 一键实现不同功能 - How can I have different functions in one button with tkinter python 如何在特定帧中的tkinter中放置不同按钮功能的输出? - How can I place the output of different button functions in tkinter in a particular frame? 如何使包含 Tkinter 复选框的循环适用于来自 function 的复选框的每个不同实例? - How can I make a loop including Tkinter Checkboxes work for every different instance of a checkbox from the function called? 如何在 tkinter 中制作具有不同数字的按钮 - how to make a button with a different number in tkinter 如何使同一事件对 tkinter 中的不同功能具有不同的含义? - How to make same event mean different things for different functions in tkinter? 如何在循环中创建多个具有不同名称的tkinter小部件? - How can I create multiple tkinter widgets with different names in a loop? 如何将函数分配给 Tkinter 中具有两个不同变量的按钮? - How can I assign a function to a button in Tkinter with two different variables? 如何为不同的 Tkinter [sub-] 菜单执行不同的回调? - How can I execute different callbacks for different Tkinter [sub-] Menus? 将Python与Tkinter结合使用,如何根据选项菜单中选择的选项,使按钮按下做不同的事情? - Using Python with Tkinter, how can I make a button press do a different thing depending on which option is selected in the option menu? Tkinter 我如何召唤分配给它们的不同命令的按钮 - Tkinter how do i summon buttons with different commands assigned to them
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM