我怎样才能成功地抽象出下面几行代码呢? (Python Tkinter 图形用户界面)

How can I successfully abstract the following lines of code? (Python Tkinter GUI)

我正在尝试在 Python 中为名为 'Chocolate Vending Machine' 的 class 任务创建一个 GUI。学生需要使用 Python 的 Tkinter。我们列出了几个巧克力品牌,例如士力架、Twix 和 Mars,并在每个品牌上贴上了价格标签。用户完成这些步骤:

  1. 输入他有多少钱的浮点值(可以是任何值)
  2. 他选择他想要的每种巧克力的数量
  3. 该值打印到控制台下:"Total Cost"
  4. 原来的余额(他原来有多少钱)减去总成本打印出新的余额

请参考以下代码。 如何抽象以下代码行使其仍然有效,但限制行数?请注意,我没有粘贴应用程序的整个代码,因为它太多了代码行。所以这里有一个片段可以缩小范围:

#----------------------Chocolate---------------------

Twix=DoubleVar()
Snickers=DoubleVar()
MarsBar=DoubleVar()
Godiva=DoubleVar()

lblTwix = Label(f1, font=('arial', 16, 'bold'), text='Twix',bg = 'powder blue',bd=19,anchor='w')
lblTwix.grid(row=2,column=0)
txtTwix = Entry(f1,font=('arial',16,'bold'),textvariable=Twix,bd=10,insertwidth=4,
                bg='powder blue',justify='right')
txtTwix.grid(row=2,column=1)

lblSnickers = Label(f1, font=('arial', 16, 'bold'), text='Snickers', bg = 'powder blue',bd=19,anchor='w')
lblSnickers.grid(row=4,column=0)
txtSnickers = Entry(f1,font=('arial',16,'bold'),textvariable=Snickers,bd=10,insertwidth=4,
                bg='powder blue',justify='right')
txtSnickers.grid(row=4,column=1)

lblMarsBar = Label(f1, font=('arial', 16, 'bold'), text='Mars Bar', bg = 'powder blue',bd=19,anchor='w')
lblMarsBar.grid(row=6,column=0)
txtMarsBar = Entry(f1,font=('arial',16,'bold'),textvariable=MarsBar,bd=10,insertwidth=4,
                bg='powder blue',justify='right')
txtMarsBar.grid(row=6,column=1)

lblGodiva = Label(f1,font=('arial',16,'bold'), text="Godiva", bg = 'powder blue',bd=19, anchor='w')
lblGodiva.grid(row=9, column=0)
txtGodiva = Entry(f1,font=('arial',16,'bold'),textvariable=Godiva,bd=10,insertwidth=4,
                bg='powder blue',justify='right')
txtGodiva.grid(row=9,column=1)

#==================================Balance, Cost=======================================

InitialBalance=DoubleVar()
Cost=StringVar()
FinalBalance=StringVar()

lblInitialBalance = Label(f1,font=('arial',20,'bold'), text="Initial Balance", bg = 'powder blue', bd=29, anchor='w')
lblInitialBalance.grid(row=2, column=10)
txtInitialBalance=Entry(f1,font=('arial',20,'bold'), textvariable=InitialBalance, bd=28, insertwidth=4,
                   bg='steel blue', justify='right')
txtInitialBalance.grid(row=2, column=12)

lblCost = Label(f1,font=('arial',20,'bold'), text="Total Cost", bg = 'powder blue',bd=29, anchor='w')
lblCost.grid(row=4, column=10)
txtCost=Entry(f1,font=('arial',20,'bold'), textvariable=Cost, bd=28, insertwidth=4,
                   bg='powder blue', justify='right')
txtCost.grid(row=4, column=12)

lblFinalBalance = Label(f1,font=('arial',20,'bold'), text="Final Balance", bg = 'powder blue',bd=29, anchor='w')
lblFinalBalance.grid(row=6, column=10)
txtFinalBalance=Entry(f1,font=('arial',20,'bold'), textvariable=FinalBalance, bd=28, insertwidth=4,
                   bg='powder blue', justify='right')
txtFinalBalance.grid(row=6, column=12)

修改后的代码:

Twix=DoubleVar()
Snickers=DoubleVar()
MarsBar=DoubleVar()
Godiva=DoubleVar()

def make_entry(frame, text, variable, row, col1, col2):
    label = Label(frame, font=('arial',20,'bold'), text=text, textvariable = variable, bg = 'powder blue', bd=19, anchor='w')
    label.grid(row=row, column=col1)
    entry=Entry(f1,font=('arial',20,'bold'), textvariable=variable, bd=28, insertwidth=4,
                       bg='steel blue', justify='right')
    entry.grid(row=row, column=col2)
    return label, entry

    make_entry(f1, "Twix", Twix, 2, 0, 1)
    make_entry(f1, "Snickers", Snickers, 4, 0, 1)
    make_entry(f1, "MarsBar", MarsBar, 6, 0, 1)
    make_entry(f1, "Godiva", Godiva, 9, 0, 1)

这里是 link 完整的非抽象代码:

https://docs.google.com/document/d/1tMJxmFAMWyc6qhTFnhoedQmj49Qkf56rJxhxB8Z3fSM/edit?usp=sharing

如您所见,上面粘贴的每一行代码都与按钮和框的样式有关,用户可以为程序输入必要的信息以完成其工作。综上所述,我重申这个问题:

将所有这些代码压缩到更少的行中并使其仍然有效的最有效方法是什么?我如何使用 classes 和 def 语句以更有效的方式重写代码?

我试图抽象上面的代码,但没有成功。感谢任何帮助。

您可以使用给定的参数定义一个函数来创建 LabelEntry

def make_entry(frame, text, variable, row, col1, col2):
    font = ('arial',16,'bold')
    label = Label(frame, font=font, text=text, bg='powder blue', bd=19, anchor='w')
    label.grid(row=row, column=col1)
    entry = Entry(frame, font=font, textvariable=variable, bg='powder blue', bd=10, insertwidth=4, justify='right')
    entry.grid(row=row, column=col2)

然后,只需为您的不同糖果调用该函数即可。

make_entry(f1, "Twix", Twix, 2, 0, 1)
make_entry(f1, "Snickers", Snickers, 4, 0, 1)
...

可能也有函数return label, entry,如果你以后需要的话,但看起来变量已经足够了。

第二组的参数有点不同:更大的字体、更粗的边框、不同深浅的蓝色。您可以为函数添加这些附加参数,或者为这些按钮创建与第一个类似的第二个函数。

或者,您也可以只创建两个循环而不是定义一个函数。特别是如果第一组和第二组条目之间的差异更大,这可能比使用两个非常相似的函数或一个具有很多参数的函数更简单。

candies = [("Twix", Twix), ("Snickers", Snickers),
           ("Mars Bar", MarsBar), ("Godiva", Godiva)]
font = ('arial',16,'bold')
for i, (name, var) in enumerate(candies, start=1):
    label = Label(f1, font=font, text=name, bg='powder blue', bd=19, anchor='w')
    label.grid(row=2*i, column=0)
    entry = Entry(f1, font=font, textvariable=var, bg='powder blue', bd=10, insertwidth=4, justify='right')
    entry.grid(row=2*i, column=1)

此外,与实际问题无关,DoubleVar 对于像巧克力棒这样的可计数数量似乎不是一个明智的选择。您的用户应该能够购买 3.14 Mars 金条吗?相反,我建议使用 IntVar.


关于你的"revised code":有两个问题:第一,函数make_entry(f1, ...)的使用不应该在函数里面,而是在根级别(无缩进)。其次,您不小心将 textvariable=variable 添加到 Label 构造函数中,它不属于该构造函数;只到 Entry.