Reputation: 1185
I am making a Tkinter text editor and I am having some trouble with classes. I have made a class with all my functions in it and a class with my mainloop. The root window opens up fine but when press the save button I get the error
Exception in Tkinter callback
Traceback (most recent call last):
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 1536, in __call__
return self.func(*args)
TypeError: unbound method saveas() must be called with F instance as first argument (got nothing instead)
I have looked at this and this example but can't figure out what is going wrong. What is my problem?
Below is my short code that illustrates the problem.
from Tkinter import *
class Main(object):
def __init__(self, root):
root.title("PyText")
self.m1=Menu(root)
self.fm=Menu(self.m1, tearoff=0)
self.fm.add_command(label="New", command=self.saveas())
self.fm.add_command(label="Open", command=self.saveas())
self.fm.add_command(label="Save", command=self.saveas())
self.fm.add_command(label="Save as...", command=self.saveas())
self.fm.add_command(label="Close", command=self.saveas())
self.fm.add_separator()
self.fm.add_command(label="Exit", command=root.quit)
self.m1.add_cascade(label="File", menu=self.fm)
self.editmenu = Menu(self.m1, tearoff=0)
self.editmenu.add_command(label="Undo", command=self.saveas())
self.editmenu.add_separator()
self.editmenu.add_command(label="Cut", command=self.saveas())
self.editmenu.add_command(label="Copy", command=self.saveas())
self.editmenu.add_command(label="Paste", command=self.saveas())
self.editmenu.add_command(label="Delete", command=self.saveas())
self.editmenu.add_command(label="Select All", command=self.saveas())
self.m1.add_cascade(label="Edit", menu=self.editmenu)
self.helpmenu = Menu(self.m1, tearoff=0)
self.helpmenu.add_command(label="Help Index", command=self.saveas())
self.helpmenu.add_command(label="About...", command=self.saveas())
self.m1.add_cascade(label="Help", menu=self.helpmenu)
root.config(menu=self.m1)
self.t1=Text(root)
self.t1.config(width=90, height=40)
self.t1.grid()
def saveas(self):
self.filewin = Toplevel()
self.e1=Entry(self.filewin)
self.e1.grid()
self.button = Button(self.filewin, text="Save", command=self.save)
self.button.grid()
def save(self):
with open(self.e1.get(), "w") as f: # this instance variable can be accessed
f.write(self.t1.get('1.0', 'end')) # added self.t1 above, and start/end
root = Tk()
app = Main(root)
root.mainloop()
Upvotes: 1
Views: 1404
Reputation: 49318
You're building your application wrong. Take the root Tkinter object-building code out of that class. You'll need a class that contains things for your Tkinter object. If you want more classes for other kinds of objects, that's fine. As it is, you're calling F.saveas
as a class method with no argument, and it's expecting self
, which is an instance of class F
, which you don't have because you never instantiated it.
from Tkinter import *
class Main(object):
def __init__(self, root):
# root.geometry("100x100") # this will make your app window tiny -
# I've commented it out for now but you'll need to look into it
self.b1 = Button(root, text="save", command=self.saveas)
self.b1.grid()
self.t1 = Text(root) # added a Text widget
self.t1.grid()
def saveas(self):
filewin = Toplevel()
self.e1=Entry(filewin) # make this an instance variable
self.e1.grid()
button = Button(filewin, text="Save", command=self.save)
button.grid()
def save(self):
with open(self.e1.get(), "w") as f: # this instance variable can be accessed
f.write(self.t1.get('1.0', 'end')) # added self.t1 above, and start/end
master = Tk()
app = Main(master)
root.mainloop()
Upvotes: 2