Python tkinter binding a function to a button

from tkinter import *

root = Tk()
root.title("Tip & Bill Calculator")

totaltxt = Label(root, text="Total", font=("Helvitca", 16))
tiptxt = Label(root, text="Tip (%)", font=("Helvitca", 16))
peopletxt = Label(root, text="people", font=("Helvitca", 16))

totaltxt.grid(row=0, sticky=E)
tiptxt.grid(row=1, sticky=E)
peopletxt.grid(row=2, sticky=E)

totalentry = Entry(root)
tipentry = Entry(root)
peopleentry = Entry(root)

totalentry.grid(row=0, column=2)
tipentry.grid(row=1, column=2)
peopleentry.grid(row=2, column=2)

ans = Label(root, text = "ANS")
ans.grid(row=4)

def answer(event):
    data1 = totalentry.get()
    data2 = tipentry.get()
    data3 = peopleentry.get()
    if tipentry.get() == 0:
        ans.configure(str((data1/data3)), text="per person")
        return
    elif data1 == 0:
        ans.configure(text="Specify the total")
        return
    elif data3 == 0 or data3 ==1:
        ans.configure(str(data1*(data2/100+1)))
        return
    elif data1 == 0 and data2 == 0 and data3 ==0:
        ans.configure(text = "Specify the values")
        return
    else:
        ans.configure(str((data1*(data2/100+1)/data3)), text="per person")
        return

bf = Frame(root)
bf.grid(row=3, columnspan=3)
calc = Button(bf, text ="Calculate", fg = "black", command = answer)
calc.bind("<Button-1>", answer)
calc.grid(row=3, column=2)

root.mainloop()

I'm trying to make a tip and bill calculator with a simple design just to learn and experiment. However, I encountered a horrible problem that kept haunting for days, I usually struggle with functions in python and I'm trying to bind a function to a calculate button, which I managed to make it appear. However, I can't manage to get it to work. After some messing around I ended with this error, when I click the calculate button.

This is the error after I click the calculate button:

TypeError: answer() missing 1 required positional argument: 'event'

Upvotes: 2

Views: 7815

Answers (1)

Terry Jan Reedy
Terry Jan Reedy

Reputation: 19144

  1. Commands bound to a button do not get an argument, as the nature of the event is already known. Delete 'event'.

  2. You also bind the answer function to an event. The result is that answer is called both without and with an event argument. Get rid of the bind call.

  3. Follow hint given by Bryan. Stop passing a digit string to .configure as a positional parameter. tk will try to interpret is as dictionary. Instead, add the number string to the rest of the label string.

  4. Like rows, columns start from 0.

  5. The frame is not needed.

The following revision works.

from tkinter import *

root = Tk()
root.title("Tip & Bill Calculator")

totaltxt = Label(root, text="Total", font=("Helvitca", 16))
tiptxt = Label(root, text="Tip (%)", font=("Helvitca", 16))
peopletxt = Label(root, text="people", font=("Helvitca", 16))

totaltxt.grid(row=0, column=0, sticky=E)
tiptxt.grid(row=1, column=0, sticky=E)
peopletxt.grid(row=2, column=0, sticky=E)

totalentry = Entry(root)
tipentry = Entry(root)
peopleentry = Entry(root)

totalentry.grid(row=0, column=1)
tipentry.grid(row=1, column=1)
peopleentry.grid(row=2, column=1)

ans = Label(root, text = "ANS")
ans.grid(row=4, column=0, columnspan=2, sticky=W)

def answer():
    total = totalentry.get()
    tip = tipentry.get()
    people = peopleentry.get()
    if not (total and tip):
        ans['text'] = 'Enter total and tip as non-0 numbers'
    else:
        total = float(total)
        tip = float(tip) / 100
        people = int(people) if people else 1
        ans['text'] = str(round(total * tip / people, 2)) + " per person"

calc = Button(root, text ="Calculate", fg = "black", command = answer)
calc.grid(row=3, column=1)

root.mainloop()

Upvotes: 1

Related Questions