What is the difference between creating a button with Button(self) as opposed to Button(parent) in a frame?
Question:
In the following code I am creating a window and a frame inside it.
Code 1:
import tkinter as tk
class MainApp(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.parent = parent
button = tk.Button(parent, text="a button")
button.pack()
root = tk.Tk()
app = MainApp(root)
app.pack(fill="both", expand=True)
root.mainloop()
Code 2:
import tkinter as tk
class MainApp(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.parent = parent
button = tk.Button(self, text="a button")
button.pack()
root = tk.Tk()
app = MainApp(root)
app.pack(fill="both", expand=True)
root.mainloop()
Then I create a button in two ways (Button(self)
and Button(parent)
).
The question is: Do the buttons, in both cases, get placed in the frame that I created (like that: tk.Frame.__init__(self, parent)
), both next to it, or one next to it and one inside it?
If both get created inside it, what’s the point in doing tk.Frame.__init__(self, parent)
if nothing goes inside it?
Answers:
In the following code I am creating a window and a frame inside it.
That is an incorrect statement. You are creating a single window which inherits from tk.Frame
. Within the class, self
represents that frame. Outside the class, that frame is app
.
Then I create a button in two ways (Button(self) and Button(parent)). The question is: Do the buttons, in both cases, get placed in the frame that I created (like that: tk.Frame.init(self, parent)), both next to it, or one next to it and one inside it?
When you do Button(self)
, the button is a child of the frame and thus will appear inside the frame.
When you do Button(parent)
the button is a child of the parent (in this case, the root window), and thus will appear outside of the frame.
You can easily see this by giving the frame a distinctive color.
import tkinter as tk
class MainApp(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent, background="pink")
self.parent = parent
button = tk.Button(parent, text="a button")
button.pack()
root = tk.Tk()
app = MainApp(root)
app.pack(fill="both", expand=True)
root.mainloop()
A widget is packed (of course) within its parent, otherwise it would not make much sense to specify the parent of a widget (unless there are other special reasons). Therefore, in your first case, the button is packed within the root (the parent of the frame), and, in the second case, the button is packed within the frame itself.
To see better what’s going on, the best solution is to set background colors of both the frame and the root. See the following example:
Code 1:
import tkinter as tk
class MainApp(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent, bg="blue")
self.parent = parent
button = tk.Button(parent, text="a button")
button.pack()
root = tk.Tk()
root.geometry("200x200+300+300")
root.config(background="yellow")
app = MainApp(root)
app.pack(fill="both", expand=True)
root.mainloop()
Result 1
Code 2:
import tkinter as tk
class MainApp(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent, bg="blue")
self.parent = parent
button = tk.Button(self, text="a button")
button.pack()
root = tk.Tk()
root.geometry("200x200+300+300")
root.config(background="yellow")
app = MainApp(root)
app.pack(fill="both", expand=True)
root.mainloop()
Result 2
Note also that frames have no size until you fill them with some widgets. Note also that you are expanding the frame (or MainApp
) and making it fill in bother vertical and horizontal directions, thus the blue takes all the window in this last case.
In the following code I am creating a window and a frame inside it.
Code 1:
import tkinter as tk
class MainApp(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.parent = parent
button = tk.Button(parent, text="a button")
button.pack()
root = tk.Tk()
app = MainApp(root)
app.pack(fill="both", expand=True)
root.mainloop()
Code 2:
import tkinter as tk
class MainApp(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.parent = parent
button = tk.Button(self, text="a button")
button.pack()
root = tk.Tk()
app = MainApp(root)
app.pack(fill="both", expand=True)
root.mainloop()
Then I create a button in two ways (Button(self)
and Button(parent)
).
The question is: Do the buttons, in both cases, get placed in the frame that I created (like that: tk.Frame.__init__(self, parent)
), both next to it, or one next to it and one inside it?
If both get created inside it, what’s the point in doing tk.Frame.__init__(self, parent)
if nothing goes inside it?
In the following code I am creating a window and a frame inside it.
That is an incorrect statement. You are creating a single window which inherits from tk.Frame
. Within the class, self
represents that frame. Outside the class, that frame is app
.
Then I create a button in two ways (Button(self) and Button(parent)). The question is: Do the buttons, in both cases, get placed in the frame that I created (like that: tk.Frame.init(self, parent)), both next to it, or one next to it and one inside it?
When you do Button(self)
, the button is a child of the frame and thus will appear inside the frame.
When you do Button(parent)
the button is a child of the parent (in this case, the root window), and thus will appear outside of the frame.
You can easily see this by giving the frame a distinctive color.
import tkinter as tk
class MainApp(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent, background="pink")
self.parent = parent
button = tk.Button(parent, text="a button")
button.pack()
root = tk.Tk()
app = MainApp(root)
app.pack(fill="both", expand=True)
root.mainloop()
A widget is packed (of course) within its parent, otherwise it would not make much sense to specify the parent of a widget (unless there are other special reasons). Therefore, in your first case, the button is packed within the root (the parent of the frame), and, in the second case, the button is packed within the frame itself.
To see better what’s going on, the best solution is to set background colors of both the frame and the root. See the following example:
Code 1:
import tkinter as tk
class MainApp(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent, bg="blue")
self.parent = parent
button = tk.Button(parent, text="a button")
button.pack()
root = tk.Tk()
root.geometry("200x200+300+300")
root.config(background="yellow")
app = MainApp(root)
app.pack(fill="both", expand=True)
root.mainloop()
Result 1
Code 2:
import tkinter as tk
class MainApp(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent, bg="blue")
self.parent = parent
button = tk.Button(self, text="a button")
button.pack()
root = tk.Tk()
root.geometry("200x200+300+300")
root.config(background="yellow")
app = MainApp(root)
app.pack(fill="both", expand=True)
root.mainloop()
Result 2
Note also that frames have no size until you fill them with some widgets. Note also that you are expanding the frame (or MainApp
) and making it fill in bother vertical and horizontal directions, thus the blue takes all the window in this last case.