Python: why must Tkinter class instantiation use a Frame? Python: why must Tkinter class instantiation use a Frame? tkinter tkinter

Python: why must Tkinter class instantiation use a Frame?


There is nothing that says a tkinter class must inherit from a frame. You can inherit from any of the tkinter widgets, or any other classs. If you have found documentation that states otherwise, that documentation is wrong. Using Frame is a logical choice since it is designed to be a container of other widgets, but it is not the only choice.

Personally I inherit from a frame because I find it convenient. Some of my GUIs need the ability to open more than one identical window. By having my main code in a Frame I am able to create multiple windows simply by creating multiple instances of the frame, and packing them in Toplevel widgets.

When you inherit from Tk, you can only have a single instance. In the real world that's usually enough, and there's absolutely nothing wrong with doing it that way. Since I personally write a fair number of tkinter programs, having them all start out exactly the same is convenient for me.

Another good choice is a Canvas since you can easily add a background image, which is not something you can do with a Frame.

Bottom line: you are absolutely not required to inherit from Frame. Inherit from whatever you want.


(the following was written in response to an edit of the original question)

In reference to this code:

from Tkinter import *class Application(Tk):  tkBtn = Button()  tkBtn.pack()app = Application()app.mainloop()

The reason you see two windows is that you're not creating the class properly. You need to call the __init__ method of the superclass before creating widgets, because that's what actually creates the root window. Because you don't, you end up with two windows. You get one that is created implicitly when you add a button to a not-yet-constructed root window, and you get another when your subclass finishes initializing.

The solution is to not take shortcuts, and instead initialize the class properly:

from Tkinter import *class Application(Tk):    def __init__(self):        Tk.__init__(self)        tkBtn = Button()        tkBtn.pack()app = Application()app.mainloop()

Note that this isn't a tkinter-specific problem. When subclassing, unless you have explicit reasons to do otherwise, you always should call the __init__ method of the superclass.

You asked for working examples, here are a couple:

You might also want to read the responses in the question Inheriting from Frame or not in a Tkinter application