tkinter grid layout: empty cells smaller than filled ones?

Question:

I have a grid layout in tkinter:

import tkinter as tk
from tkinter import ttk

root = tk.Tk()
root.geometry('500x500')

root.rowconfigure(0, weight = 1)
root.rowconfigure(1, weight = 1)
root.rowconfigure(2, weight = 1)
root.columnconfigure(0, weight = 1)
root.columnconfigure(1, weight = 1)
root.columnconfigure(2, weight = 1)
root.columnconfigure(3, weight = 1)

ttk.Label(root, text = 'Area 1', background = 'red').grid(row = 0, column = 0, sticky = 'NSWE')
ttk.Label(root, text = 'Area 2', background = 'blue').grid(row = 1, column = 2, sticky = 'NSWE')

root.mainloop()

This creates this layout:
enter image description here

I know there are 4 columns and 3 rows but I am confused about the second and the last column (i.e. the ones without widgets) are narrower than the ones that have filled cells. When I measure it I get a default width for filled cells of about 215 while the empty ones only have 165. Is there a reason for this?

I suppose one way to fix it would be to add a label in column 1 and 3 with an empty string as text and give all labels a width. But that seems quite hacky, is there a better solution?

I guess I am ultimately confused about the fact that the width of a widget affects the width of a grid cell quite a bit. Can someone explain the logic behind it? I looked at lots of grid tutorials but haven’t found one that talks about it.

Asked By: Another_coder

||

Answers:

When I measure it I get a default width for filled cells of about 215 while the empty ones only have 165. Is there a reason for this?

The reason is that empty rows and empty columns have a default size of zero. In your code you’re giving a non-zero weight to all columns, so after grid has added the widgets, it divides the extra space up equally among the columns with a non-zero weight.

Lets say that the window has 200 extra pixels to allocate. Let’s also say that the columns with widgets are 100 pixels each. Initially, column 0 will be 100 pixels wide, column 1 will be zero pixels wide, column 2 will be zero pixels, and column 3 will be 100 pixels.

Now, grid has to allocate the 200 extra pixels. That means that each column gets 50 pixels. Column 0 ends up being 150 pixels wide (100 + 50), column 1 will be 50 (0+50), and columns 2 and 3 are identical to 0 and 1.

I suppose one way to fix it would be to add a label in column 1 and 3 with an empty string as text and give all labels a width. But that seems quite hacky, is there a better solution?

If you give them each the same value for the uniform option, and give them all the same value for weight, all columns will be the same size.

root.columnconfigure(0, weight = 1, uniform="a")
root.columnconfigure(1, weight = 1, uniform="a")
root.columnconfigure(2, weight = 1, uniform="a")
root.columnconfigure(3, weight = 1, uniform="a")

Note: the value for uniform is irrelevant. It can be any string. The important thing is that it needs to be the same string for all columns that you want to have the same size.

I guess I am ultimately confused about the fact that the width of a widget affects the width of a grid cell quite a bit.

I’m not sure what to say about that. That’s how grid is designed to work, and these defaults work quite well in practice.

For the official documentation of how grid works see The grid algorithm in the tcl/tk man page for grid.

Answered By: Bryan Oakley
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.