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?

Asked By: Vamoos

||

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()
Answered By: Bryan Oakley

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

enter image description here

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

enter image description here

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.

Answered By: nbro
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.