DebianFox
DebianFox

Reputation: 63

Tkinter: How to pass arguments from Entry widgets to function?

I have created two Entry widgets called name_entry and passwd_entry. After the user enters his name and password, the program should subsequently list it if the user clicks on the Submit button.

Unfortunately this is not working. I'm trying to write it within a class and to pass it as an argument to my submit function.

I receive this error:

File "/usr/lib/python3.7/tkinter/__init__.py", line 1705, in __call__
    return self.func(*args)
TypeError: submit() missing 2 required positional arguments: 'var_name' and 'var_passwd'

Code:

#/usr/bin/python3.7
from tkinter import *

class Window (Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.master = master
        self.init_window()

    def init_window(self):
        self.master.title("GUI")
        self.pack(fill=BOTH, expand=1)

        var_name = StringVar()
        var_passwd = StringVar()

        name = Label(self, text="Name: ")
        name.place(x = 0, y = 0)
        name_entry = Entry(root, textvariable = var_name)
        name_entry.place(x = 90, y =0)

        passwd = Label(self, text="Password: ")
        passwd.place(x = 0, y = 90)
        passwd_entry = Entry(root, textvariable = var_passwd)
        passwd_entry.place(x = 90, y = 90)

        Knop1 = Button(self, text="Submit", command=self.submit)
        Knop1.place(x = 180, y=180)

    def submit (self, var_name, var_passwd):
        naam = var_name.get()
        var_passwd = var_passwd.get()
        print("The name is: ", naam)
        print("The password is: ", var_passwd)


root = Tk()
root.geometry("500x300")
app = Window(root)
app.mainloop()

Can anyone help me? I'm also looking for a good Tkinter tutorial where OOP is being used.

Upvotes: 1

Views: 1771

Answers (2)

Bryan Oakley
Bryan Oakley

Reputation: 385900

As a general rule it's best of the command of a button calls a function that accepts no arguments. Since you've made a special-purpose function that always operates on the same variables, you can have the directly access the variables.

First, make the variables an attribute of the class:

def init_window(self):
    ...
    self.var_name = StringVar()
    self.var_passwd = StringVar()
    ..

Then, define your function to access those variables:

def submit (self):
    naam = self.var_name.get()
    var_passwd = self.var_passwd.get()
    ...

And finally, modify how your button calls this function:

Knop1 = Button(self, text="Submit", command=self.submit)

Note: if you're not using the special properties of a tkinter variable (such as the trace mechanism), you don't need to use StringVar at all.

Example:

def init_window(self):
    ...
    self.name_entry = Entry(root, textvariable = var_name)
    self.passwd_entry = Entry(root, textvariable =var_passwd)
    ...

def submit (self):
    naam = self.name_entry.get()
    var_passwd = self.passwd_entry.get()
    ...

Upvotes: 0

L.Clarkson
L.Clarkson

Reputation: 492

You haven't passed the variables to the submit function button. For simple cases like this, you can use a lambda expression as a link between Tkinter and the callback function, otherwise Python will call the callback function before creating the widget: https://effbot.org/zone/tkinter-callbacks.htm

from tkinter import *

class Window (Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.master = master
        self.init_window()

    def init_window(self):
        self.master.title("GUI")
        self.pack(fill=BOTH, expand=1)

        var_name = StringVar()
        var_passwd = StringVar()

        name = Label(self, text="Name: ")
        name.place(x = 0, y = 0)
        name_entry = Entry(root, textvariable = var_name)
        name_entry.place(x = 90, y =0)

        passwd = Label(self, text="Password: ")
        passwd.place(x = 0, y = 90)
        passwd_entry = Entry(root, textvariable =var_passwd)
        passwd_entry.place(x = 90, y = 90)

        # Changed this line
        Knop1 = Button(self, text="Submit", command=lambda: self.submit(var_name, var_passwd))
        Knop1.place(x = 180, y=180)

    def submit (self, var_name, var_passwd):
        naam = var_name.get()
        var_passwd = var_passwd.get()
        print("The name is: ", naam)
        print("The password is: ", var_passwd)

root = Tk()
root.geometry("500x300")
app = Window(root)
app.mainloop()

To address your question about OOP with tkinter, this question has some good advice: Best way to structure a tkinter application?

Upvotes: 1

Related Questions