Partho63
Partho63

Reputation: 3117

Calling function from different class gives TypeError: missing 1 required positional argument

I was trying to build something where I wanted to give separate class to each frames. Now when I called onSet function of AddWidgets class it shows an

ERROR: TypeError: onSet() missing 1 required positional argument: 'text'

What am I doing wrong? And how to solve this? My Code is given below:

import tkinter as tk
from tkinter import ttk


class MainWindow:
    def __init__(self, master):
        self.master = master
        self.master.title("Class Function")
        self.master.wm_iconbitmap('icon.ico')
        self.master.geometry("360x240+100+100")
        self.frame1 = ttk.Frame(self.master)
        self.frame1.grid(row=0, column=0, padx=16, pady=16)
        self.frame2 = ttk.Frame(self.master)
        self.frame2.grid(row=0, column=1, padx=16, pady=16)

        self.add = AddWidgets(self.frame1)
        self.edit = EditWidgets(self.frame2)


class AddWidgets:
    def __init__(self, master):
        self.master = master
        self.create_widgets()

    def create_widgets(self):
        self.label1 = ttk.Label(self.master, text="0")
        self.label1.grid(row=0, column=0, padx=4, pady=4)

    def onSet(self, text):
        self.label1.configure(text=text)


class EditWidgets:
    def __init__(self, master):
        self.master = master
        self.create_widgets()

    def create_widgets(self):
        def onEdit():
            self.send_text = self.entry_text.get()
            AddWidgets.onSet(self.send_text)

        self.entry_text = tk.StringVar()
        self.entry1 = ttk.Entry(self.master, textvariable=self.entry_text)
        self.entry1.grid(row=0, column=0, padx=4, pady=4)
        self.button1 = ttk.Button(self.master, text="edit", command=onEdit)
        self.button1.grid(row=0, column=1, padx=4, pady=4)



def main():
    root = tk.Tk()
    app = MainWindow(root)
    root.mainloop()


if __name__ == '__main__':
    main()

I am new to Python and tkinter. I want to build a desktop app/software. I want to develop the software by following MVC pattern. So any resource for MVC in tkinter and suggestions on how can I improve my coding, software development process would be appreciated.

Upvotes: 1

Views: 969

Answers (1)

toti08
toti08

Reputation: 2454

The method onSet requires the instance of the class as a first argument, while you're only passing the text argument. So when you call your onSet method you should pass the instance of the AddWidgets class as first argument. You're instantiating this class in the MainWindow class:

self.add = AddWidgets(self.frame1)

So you should pass the self.add variable to the onSet function. In order to do that you should have your EditWidget class accept an additional parameter widget:

class MainWindow:
    def __init__(self, master):
        self.master = master
        self.master.title("Class Function")
        self.master.wm_iconbitmap('icon.ico')
        self.master.geometry("360x240+100+100")
        self.frame1 = ttk.Frame(self.master)
        self.frame1.grid(row=0, column=0, padx=16, pady=16)
        self.frame2 = ttk.Frame(self.master)
        self.frame2.grid(row=0, column=1, padx=16, pady=16)

        self.add = AddWidgets(self.frame1)
        self.edit = EditWidgets(self.frame2, self.add) <--Add parameter self.add


class AddWidgets:
    def __init__(self, master):
        self.master = master
        self.create_widgets()

    def create_widgets(self):
        self.label1 = ttk.Label(self.master, text="0")
        self.label1.grid(row=0, column=0, padx=4, pady=4)

    def onSet(self, text):
        self.label1.configure(text=text)


class EditWidgets:
    def __init__(self, master, widget): <-- add parameter widget 
        self.master = master
        self.create_widgets()
        self.widget = widget

    def create_widgets(self):
        def onEdit():
            self.send_text = self.entry_text.get()
            self.widget.onSet(self.send_text) <--call onSet from widget instance
[...]

EDIT: If you want to create different tabs, all with the same widgets, one approach could be the following: you create a MainWindow class, where you add all the tabs to your window using the Notebook class.

Then you create a Add Widgets class that adds the required widgets to a frame. You instantiate this class on each of the created tabs, in order to populate them with the widgets.

In order to get the values of the variables you set in each tab you can write a method getEntryValue (or whatever name) that returns the value set on the entry. Something like this:

class MainWindow:
    def __init__(self, master):
        self.master = master
        self.master.title("Class Function")

        self.master.geometry("360x240+100+100")

        n = ttk.Notebook(master)
        self.f1 = ttk.Frame(n)   # Create first tab
        self.f2 = ttk.Frame(n)   # Create second tab
        n.add(self.f1, text='One')
        n.add(self.f2, text='Two')     
        n.pack()        

        self.widget1 = AddWidgets(self.f1)
        self.widget2 = AddWidgets(self.f2)


class AddWidgets:
    def __init__(self, master):
        self.master = master
        self.create_widgets()

    def create_widgets(self):
        def onEdit():
            send_text = self.entry_text.get()
            self.label1.configure(text = send_text)

        self.label1 = ttk.Label(self.master, text="0")
        self.label1.grid(row=0, column=0, padx=4, pady=4)

        self.entry_text = tk.StringVar()
        self.entry1 = ttk.Entry(self.master, textvariable=self.entry_text)
        self.entry1.grid(row=0, column=1, padx=4, pady=4)

        self.button1 = ttk.Button(self.master, text="edit", command=onEdit)
        self.button1.grid(row=0, column=2, padx=4, pady=4)

    def getEntryText(self):
        return self.entry_text.get()

Hope it helps.

Upvotes: 1

Related Questions