I am making a basic GUI app using tkinter that gathers user input to populate a docx template. There is too much code so I'll just post where I think the problem is. Here's my button.
self.my_button = Button(self.master, text="Create the Contract",
command=lambda: self.create_contract(self.name_entry.get(),
self.address_entry.get(),
self.city_entry.get(),
self.postal_code_entry.get(),
self.phone_entry.get(),
self.email_entry.get(),
self.arrival_entry.get(),
self.departure_entry.get(),
self.total_nights_entry.get(),
self.before_tax_entry.get(),
self.total_nights_entry.get(),
calculations.gst(self.before_tax_entry.get()),
calculations.tvq(self.before_tax_entry.get()),
calculations.minitax(self.before_tax_entry.get())
))
self.my_button.grid(row=10, column=0)
self.master.mainloop()
def create_contract(self, name, address, city, postal_code, phone, email, arrival, departure, before_tax, total_nights, gst_tax, tvq_tax, mini_tax):
contract_template.CreateContract(name, address, city, postal_code, phone, email, arrival, departure, before_tax, total_nights, gst_tax, tvq_tax, mini_tax)
calculations:
def gst(before_tax):
guest_gst = int(before_tax) * 0.05
return guest_gst
def tvq(before_tax):
guest_tvq = int(before_tax) * 0.09975
return guest_tvq
def minitax(total_nights):
guest_minitax = int(total_nights) * 2
return guest_minitax
Right now, when I run the app, the GUI gets displayed, I have all my entries and button, but when I click the button:
>>> import GUIcontract
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1486, in __call__
return self.func(*args)
File "GUIcontract.py", line 76, in <lambda>
calculations.minitax(self.before_tax_entry.get())
TypeError: create_contract() takes exactly 14 arguments (15 given)
>>>
I have been going at this for the last 8 hours. I wish my laptop were sturdier so I could throw it. Clearly the problem is with
calculations.minitax(self.before_tax_entry.get())
The simple solution is to not use lambda in this way. You're making things way too hard. Since all of those variables are attributes on the object, you can get them in the callback. There's no reason to pass them into the function.
self.my_button = Button(..., command=self.create_contract)
...
def create_contract(self):
name = self.name_entry.get()
address = self.address_entry.get()
...
The end result is the same, but the code is much easier to understand and manage. Long lists of arguments are prone to this sort of very common error (passing in the wrong number of arguments), so it's best to avoid long argument lists whenever possible.
A good rule of thumb is to never use a lambda if you have to pass more than a couple arguments.