24

I am using grid() to place widgets in a tkinter window. I am trying to put a label on the horizontal center of a window and have it stay there, even if the window is resized. How could I go about doing this?

I don't want to use pack(), by the way. I would like to keep using grid().

Nae
  • 14,209
  • 7
  • 52
  • 79
L4undry
  • 281
  • 1
  • 4
  • 16

4 Answers4

25

There's no trick -- the widget is centered in the area allocated to it by default. Simply place a label in a cell without any sticky attributes and it will be centered.

Now, the other question is, how to get the area it is allocated to be centered. That depends on many other factors, such as what other widgets are there, how they are arranged, etc.

Here's a simple example showing a single centered label. It does this by making sure the row and column it is in takes up all extra space. Notice that the label stays centered no matter how big you make the window.

import Tkinter as tk

class Example(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="This should be centered")
        label.grid(row=1, column=1)
        self.grid_rowconfigure(1, weight=1)
        self.grid_columnconfigure(1, weight=1)

if __name__ == "__main__":
    root = tk.Tk()
    Example(root).grid(sticky="nsew")
    root.grid_rowconfigure(0, weight=1)
    root.grid_columnconfigure(0, weight=1)
    root.mainloop()

You can get a similar effect by giving a weight to all rows and columns except the one with the label.

import Tkinter as tk

class Example(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="This should be centered")
        label.grid(row=1, column=1)

        self.grid_rowconfigure(0, weight=1)
        self.grid_rowconfigure(2, weight=1)
        self.grid_columnconfigure(0, weight=1)
        self.grid_columnconfigure(2, weight=1)

if __name__ == "__main__":
    root = tk.Tk()
    Example(root).grid(sticky="nsew")
    root.grid_rowconfigure(0, weight=1)
    root.grid_columnconfigure(0, weight=1)

    root.mainloop()
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • This looks extremely complicated. Also, it used pack. I just want to use the grid, because the other widgets have to use grid. – L4undry Oct 09 '15 at 21:08
  • @Legodog5678: the fact it uses pack is irrelevant. It's only using pack for the boilerplate around the example. It can be grid just as easily. I'll change it if that makes you more comfortable. Without seeing your actual code I can't make it any less complicated -- that first example only requires three lines of code, the rest of the code is just boilerplate. To fix your specific code is probably just a matter of adding row and column weights -- an extra step required by grid that isn't required by pack. – Bryan Oakley Oct 09 '15 at 21:19
  • 2
    Just give the row and column in which the label appears a weight of 1 and be sure not to specify a sticky attribute. By default the row and column weight is set to zero, which means neither will grow to fill in any extra space in the widget. Setting it to 1 means it'll fill in that space and grow linearly as the window gets expanded by the user. As Bryan mentioned, this is an extra step that is necessary when using grid that is not needed when using pack. – Daniel Kocevski Apr 04 '18 at 17:53
4

There is nothing special required. A widget will be in the middle of it's parent automatically. What is required to to tell the parent to fill all available space.

from tkinter import *
root = Tk()
root.geometry("500x500+0+0")
frmMain = Frame(root,bg="blue")

startbutton = Button(frmMain, text="Start",height=1,width=4)
startbutton.grid()

#Configure the row/col of our frame and root window to be resizable and fill all available space
frmMain.grid(row=0, column=0, sticky="NESW")
frmMain.grid_rowconfigure(0, weight=1)
frmMain.grid_columnconfigure(0, weight=1)
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)

root.mainloop()

This uses grid rather than pack to place the widgets and the grid is configured to fill the entire size of the window. The button will appear in the centre regardless of the size of the window.

scotty3785
  • 6,763
  • 1
  • 25
  • 35
2

This worked for me:

    lbl1 = Label(self, text='some text')     
    lbl1.grid(row=1, column=1, sticky='e')  # right aligned
    # sticky='w'  # left aligned
    # sticky=''  # centered (or no sticky)
MichaelDL
  • 57
  • 4
1

There is another way although it is not .grid it is .place. I found that when using .grid and sticky to centre, the widget would not centre if you were only using one column.

label1 = Label(loginWindow, text="Please Log In", font=("Arial", 25))
label1.place(anchor = CENTER, relx = .5, rely = .2)

Where relx and rely is the % of the screen it is located, and anchor=CENTER centres all the widgets.