Search code examples
pythonclasstkintertkinter-entry

Argument won't pass


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())

Solution

  • 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.