Search code examples
pythontkintertkinter-layout

Tkinter Parent Frame seems to shrinks inside Button


I'm struggling to display a Button inside a Frame (which will contain other buttons). The root Window I'll put this Frame into has to be organized as a Grid (there will be more widgets), but the Frame has to be organized with pack(). My aim is to make the Frame fill the Grid cell it is assigned to, and display the button inside this frame.

However, when I launch this program, the frame seems to disappear or to shrink inside the button.

How can I make the Frame keep its original dimensions with the Button inside?

from tkinter import *

root = Tk()
root.geometry('300x300')

frame=Frame(root, bg="green", width=150, height=150)
frame.grid(row=0, column=0)

Breset=Button(frame,text='Reset', bg='pink')
Breset.pack()

root.mainloop()

Solution

  • How can I make the Frame keep its original dimensions with the Button inside?

    You almost never want to do that. If you're putting more widgets into it, the frame will naturally pick the right size to fit everything.

    If you instead want to have the frame fill the window, you would do that by using various grid options. Though, if you want the frame to always fill the whole window, that's easier to do with pack than with grid.

    Solution with pack

    To get frame to fill the root window, just use the fill and expand options with pack:

    frame.pack(fill="both", expand=True)
    

    Solution with grid

    Using grid requires a couple more steps. First, you need to use the sticky option so that the frame fills the space it is allocated. Next, you need to tell grid to give unallocated space to the frame.

    root.grid_rowconfigure(0, weight=1)
    root.grid_columnconfigure(0, weight=1)
    frame.grid(row=0, column=0, sticky="nsew")
    

    Turning off the automatic resizing of the frame

    What you originally asked for is called geometry propagation - that's the feature where the size of the children propagate up to the parent. You can turn it off with grid_propagate or pack_propagate, depending on what you're using for the child widgets. In your case you are using pack for the button inside the frame:

    frame.pack_propagate(False)
    

    This is nearly always the worst of the three solutions. The whole point of the geometry managers pack and grid is to let tkinter do all the work of deciding what size widgets should be.