How do I center a frame within a frame in Tkinter?

32,290

Solution 1

pack it to fill in all directions. Add padding as needed.

Or, use place which lets you use relative or absolute positioning. You can use a relative x/y of .5/.5 and an anchor of "c" (center).

import Tkinter as tk

root=tk.Tk()
f1 = tk.Frame(width=200, height=200, background="red")
f2 = tk.Frame(width=100, height=100, background="blue")

f1.pack(fill="both", expand=True, padx=20, pady=20)
f2.place(in_=f1, anchor="c", relx=.5, rely=.5)

root.mainloop()

Solution 2

If you want to center a widget (like a frame) inside a frame, the easiest way to do it is via .grid(). If you use .pack(), you end up stuck along one of the edges, since pack() has the side keyword.

If you use .place(), then you're stuck forcing the size of the outer frame (which normally you don't have to do, but you've already done it, so it's not an issue), because placed widgets aren't detected when the frame autosizes like with packed or gridded widgets. I'm not sure why, but that's the way it is.

So, in general, the best way to center a widget inside a frame is to grid the widget into the frame. (The sticky option defaults to CENTER.) And then, if you want to be able to resize the outer frame and have the widget stay centered, you need to allow the outer frame's cell to expand/grow. You would do this via the .grid_rowconfigure() etc commands. So, an example might be:

        widget = Widget(frame, ...)
        widget.grid(row=0, column=0, sticky="")
        frame.grid_rowconfigure(0, weight=1)
        frame.grid_columnconfigure(0, weight=1)
Share:
32,290
rectangletangle
Author by

rectangletangle

Updated on July 09, 2022

Comments

  • rectangletangle
    rectangletangle almost 2 years

    I have a frame that I fixed the size of using the grid_propagate() method. I'd like to center a frame within this frame. How do I go about this?

  • wsaleem
    wsaleem over 8 years
    It is slightly confusing as neither f1 nor f2 declare a parent. How does f1 know to get packed in root? Also, 2 different geometry managers are being mixed. This is warned against everywhere as bad practice. However, it works, and solves a problem I have been stuck with for hours. So +1!
  • Russell Smith
    Russell Smith over 8 years
    @wsaleem: Every window except the root window must have a parent. The root window is the default when a widget doesn't explicitly specify a parent. As for mixing pack and place (and/or grid): that's quite all right -- even preferable -- in an application as a whole. You just can't mix them in the same containing window. In this case f1 is being managed by the root window and f2 is being managed by f1 (because of the in_ parameter.
  • Gary02127
    Gary02127 over 4 years
    place() is fine when you already have to force the size of the outer frame. But normally I avoid place() because the frame does not "sense" the size of placed widgets when autosizing. Please see my answer below.