How to center a tkinter widget in a sticky frame

littlefiredragon picture littlefiredragon · Nov 13, 2014 · Viewed 22.8k times · Source

I'm writing a game in python3 using tkinter, and I'm having a little trouble getting the grid to do what I want it to do. I've looked through at least five pages of google results including stack overflow answers for every variant of how to ask this question I can think of. I finally just gave in and created this account to ask about this.

What I've got: A button (newGameButton) and a label (messageBox) centered in a frame (topBar) which is itself centered but does not span the entire window (contentFrame) horizontally.

The best I've managed to get (by putting sticky=W+E on topBar): Frame now spans the whole window, button and label remain the same size (sticky on the label didn't do a thing, and sticky on the button only made it as wide as the label), and are now stuck against the left side of the topBar.

What I want it to do: have the frame span the whole window, with the label also spanning the whole window, and the button centered.

The reason topBar is columnspan=23 is that the rest of the stuff in the content frame is 23 columns wide (including the 0 column). The reason I have the button and label in a frame is that I'd like that entire box surrounding them to have a border effect.

Code:

self.contentFrame = Frame(self.root)
self.contentFrame.grid(row=0, column=0)
self.topBar = Frame(self.contentFrame, border=2, relief=RAISED)
self.topBar.grid(row=0, column=0, columnspan=23)
self.newGameButton = Button(self.topBar, text="New Game")
self.newGameButton.grid(row=0, column=0)
self.messageBox = Label(self.topBar, textvariable=self.message, height=2)
self.messageBox.grid(row=1, column=0, sticky=W+E)

Has anyone got any ideas? I'm pretty desperate at this point.

Answer

Bryan Oakley picture Bryan Oakley · Nov 13, 2014

The problem is that none of your columns have any weight. It is the weight attribute that decides what columns (and rows) get any extra space. Since none of your columns have a non-zero weight, none of the extra space is allocated to them, so they stay as small as they can be.

As a rule of thumb, you should always give at least one row and one column in a frame a non-zero weight. In your case, giving row 0 and column 0 a weight of 1 for all of the frames seems to work:

self.root.grid_columnconfigure(0, weight=1)
self.root.grid_rowconfigure(0, weight=1)
self.contentFrame.grid_columnconfigure(0, weight=1)
self.contentFrame.grid_rowconfigure(0, weight=1)
self.topBar.grid_columnconfigure(0, weight=1)
self.topBar.grid_rowconfigure(0, weight=1)