littlefiredragon
littlefiredragon

Reputation: 123

How to center a tkinter widget in a sticky frame

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.

Upvotes: 12

Views: 38107

Answers (2)

timeyyy
timeyyy

Reputation: 704

by using 'how to make tkinter grid expand' in google i came across the problem.

quote from Bryan Oakley

Rows and columns have "weight" which describes how they grow or shrink to fill extra space >in the master. By default a row or column has a weight of zero, which means you've told the >label to fill the column but you haven't told the column to fill the master frame.

To fix this, give the column a weight.

class Test():
    def __init__(self,root):
        self.root = root
        self.root.columnconfigure(0, weight=1)
        self.root.config(bg='green')
        self.message = 'test message'

        self.contentFrame = Frame(self.root)
        self.contentFrame.config(background='black',borderwidth=5,relief ='sunken')
        self.contentFrame.grid(row=0, column=0, sticky='news')
        self.contentFrame.columnconfigure(0, weight=1)

        self.topBar = Frame(self.contentFrame, border=2, relief=RAISED)
        self.topBar.grid(row=0, column=0, columnspan=23,sticky=W+E)
        self.topBar.config(background='blue')
        self.topBar.columnconfigure(0, weight=1)

        self.newGameButton = Button(self.topBar, text="New Game")
        self.newGameButton.grid(row=0, column=0)
        self.newGameButton.config(background='red')

        self.messageBox = Label(self.topBar, text=self.message, height=2)
        self.messageBox.grid(row=1, column=0, columnspan=1,sticky=W+E)
        self.messageBox.config(background='yellow')

Test(root)

Upvotes: 1

Bryan Oakley
Bryan Oakley

Reputation: 386285

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)

Upvotes: 7

Related Questions