Reputation: 45
I want to create a button that uses a function (SaveFile) from other class but it throws TypeError.
"TypeError: SaveFile() missing 1 required positional argument: 'self'"
My code is:
import tkinter as tk
class App1(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
tk.Button(self, text="Browse", command=self.SaveFile).grid(row=4, column=4)
self.t1 = tk.Text(self, height=1, width=40, font="Times 9")
self.t1.grid(row=2, column=3)
def SaveFile(self):
global name2
name2 = asksaveasfilename(initialdir="\\", filetypes=(("Html Files", "*.html"),("All Files","*.*")),
title = "Output path.")
self.t1.delete("1.0", tk.END)
self.t1.insert(tk.END, name2)
class App2(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.b1 = tk.Button(self, text="Browse", command=App1.SaveFile)
self.b1.grid(row=2, column=4)
Upvotes: 1
Views: 1240
Reputation: 5933
ok for a more specific example:
import tkinter as tk
class App1(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
tk.Button(self, text="Browse", command=self.SaveFile).grid(row=4, column=4)
self.t1 = tk.Text(self, height=1, width=40, font="Times 9")
self.t1.grid(row=2, column=3)
def SaveFile(self):
global name2
name2 = asksaveasfilename(initialdir="\\", filetypes=(("Html Files", "*.html"),("All Files","*.*")),
title = "Output path.")
self.t1.delete("1.0", tk.END)
self.t1.insert(tk.END, name2)
class App2(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.b1 = tk.Button(self, text="Browse", command=App1.SaveFile)
self.b1.grid(row=2, column=4)
app1_inst = App1(parent, controller) # this creates an instance
app2_inst = App2(parent, controller) # this also creates an instance
App1.SaveFile # this is being called a class method, it is attached to the class so self does not get passed
app1_inst.SaveFile # is being called as an instance method where self = app1_inst
because app2_inst does not have any reference to app1_inst it cannot call it as an instance method. calling App1.SaveFile does not pass the instance in because it doesn't know if there even is an instance.
you need to change the definition of App2 to be able to pass in (and possible keep reference to) an instance of App1.
e.g. import tkinter as tk
class App1(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
tk.Button(self, text="Browse", command=self.SaveFile).grid(row=4, column=4)
self.t1 = tk.Text(self, height=1, width=40, font="Times 9")
self.t1.grid(row=2, column=3)
def SaveFile(self):
global name2
name2 = asksaveasfilename(initialdir="\\", filetypes=(("Html Files", "*.html"),("All Files","*.*")),
title = "Output path.")
self.t1.delete("1.0", tk.END)
self.t1.insert(tk.END, name2)
class App2(tk.Frame):
def __init__(self, parent, controller, app1):
tk.Frame.__init__(self, parent)
self.app1 = app1
self.b1 = tk.Button(self, text="Browse", command=self.app1.SaveFile)
self.b1.grid(row=2, column=4)
app1_inst = App1(parent, controller)
app2_inst = App2(parent, controller, app1_inst)
Upvotes: 3