Home > Software engineering >  How do I fix the following error in Tkinter on __init__ function?
How do I fix the following error in Tkinter on __init__ function?

Time:07-21

I'm brand new to Tkinter, and am building a tiny UI for interaction with a ML program. Here's the code I'm using for the UI window I've created:

from tkinter import *
from tkinter import ttk

class UI:

    def __init__(self, root):

        root.title("Retirement Savings Estimator")

        mainframe = ttk.Frame(root, padding="3 3 12 12")
        mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
        root.columnconfigure(0, weight=1)
        root.rowconfigure(0, weight=1)

        self.age = IntVar()
        self.age = ttk.Entry(mainframe, width=7, textvariable=self.age)
        self.age.grid(column=2, row=1, sticky=(W, E))
        ttk.Label(mainframe, text ="Enter your age: ").grid(column=1, row=1, sticky=(W, E))

        self.yearly_salary = StringVar()
        self.yearly_salary = ttk.Entry(mainframe, width=7, textvariable=self.yearly_salary)
        self.yearly_salary.grid(column=2, row=2, sticky=(W, E))
        ttk.Label(mainframe, text="Enter your gross yearly wages: ").grid(column=1, row=2, sticky=(W, E))

        for child in mainframe.winfo_children():
            child.grid_configure(padx=5, pady=5)

        ttk.Label(mainframe, text="Press the Calculate button to get your estimate: ").grid(column=1, row=3, sticky=(W, E))
        action = ttk.Button(mainframe, text="Calculate", default = "active", command = UI).grid(column=2, row=3, sticky=(W, E))
        self.age.focus()
        root.bind('<Return>', action)
        
    def predict_savings(*args, root):
        try:  
            user_age = int(self.age.get())
            yr_salary = float(self.yearly_salary.get())
            estimate = regr.predict(user_age, yr_salary)
            ttk.Label(mainframe, text="Your Estimated Amount to Save For Retirement: "   estimate).grid(column=1, row=4, sticky=(W, E))
        except ValueError:
            pass
        
root = Tk()   
UI(root)
root.mainloop()

Here's the error message I'm getting when pressing the 'Calculate' button in the UI window:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\jesst\anaconda3\lib\tkinter\__init__.py", line 1892, in __call__
    return self.func(*args)
TypeError: __init__() missing 1 required positional argument: 'root'

I've tried adding 'root' to the predict_savings() function to see if this fixes the issue, and a different error generates. I'm not sure what else to try. Any ideas would be excellent.

CodePudding user response:

The error is this line of code:

action = ttk.Button(mainframe, text="Calculate", default = "active", command = UI).grid(column=2, row=3, sticky=(W, E))

You are asking tkinter to create a new instance of UI when the button is clicked. However, UI is defined to need root as one of the parameters. When you click the button, no parameters are passed which is why you get the error.

Since the button exists inside UI, and predict_savings is inside UI, the proper solution is to have the button call self.predict_savings. Also, predict_savings shouldn't require an argument. It doesn't use the arguments so I see no reason to require them. It does, however, require the self parameter like any other class method.

    ...
    action = ttk.Button(..., command = self.predict_savings)...
    ...

def predict_savings(self):
    ...



CodePudding user response:

The line below creates a new instance of the class UI.

action = ttk.Button(mainframe, text="Calculate", default = "active", command = UI).grid(column=2, row=3, sticky=(W, E))

When we press the "Calculate" button, we expect to see the estimate, not a new window. The estimate function is self.predict_savings, so we should replace command = UI with command = lambda: self.predict_savings().

action = ttk.Button(mainframe, text="Calculate", default = "active", command = lambda: self.predict_savings()).grid(column=2, row=3, sticky=(W, E))
  • Related