I have the following script, which uses Tkinter:
import tkinter as tk
class Application(tk.Frame):
def __init__(self, master):
frame = tk.Frame(master)
frame.pack
self.PRINT = tk.Button(frame, text = 'Print', fg = 'Red', command = self.Print())
self.PRINT.pack(side = 'left')
self.QUIT = tk.Button(frame, text = 'Quit', fg = 'Red', command = self.quit())
self.QUIT.pack(side = 'left')
def Print(self):
print('at least somethings working')
root = tk.Tk()
b = Application(root)
root.mainloop()
When I run it, I get the following error:
AttributeError: 'Application' object has no attribute 'tk'
Why do I get this error?
I ran your script here and got this stack trace:
Traceback (most recent call last):
File "t.py", line 23, in <module>
b = Application(root)
File "t.py", line 15, in __init__
self.QUIT = tk.Button(frame, text = 'Quit', fg = 'Red', command = self.quit())
File "/usr/lib/python3.6/tkinter/__init__.py", line 1283, in quit
self.tk.quit()
AttributeError: 'Application' object has no attribute 'tk'
The error message appears at the end but the entire stack is important! Let's analyze it.
Apparently, there is an object, instance of an Application
class, that has no tk
attribute. Makes sense: we created this class, and we did not add this attribute.
Well, the main loop expects an attribute to exist! What happens is, our class extends tkinter.Frame
, and a frame need this tk
attribute. Luckily, we do not have to think how to create it: since all frames need it, the frame initializer (its __init__()
method) knows how to set this attribute.
What we have to do, then, is just to call the tkinter.Frame
initializer in our own initializer. This can be easily done by calling the __init__()
directly from tk.Frame
, passing the self
variable:
tk.Frame.__init__(self, master)
The entire script will be this, then:
import tkinter as tk
class Application(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
frame = tk.Frame(master)
frame.pack
self.PRINT = tk.Button(frame, text = 'Print', fg = 'Red', command = self.Print())
self.PRINT.pack(side = 'left')
self.QUIT = tk.Button(frame, text = 'Quit', fg = 'Red', command = self.quit())
self.QUIT.pack(side = 'left')
def Print(self):
print('at least somethings working')
root = tk.Tk()
b = Application(root)
root.mainloop()
Now, there will be some other bugs in your script, you'll find soon ;) There is also some complications related to multiple inheritance that can be solved with the super()
function. Nonetheless, this is the solution for your first bug.