How to create a self resizing grid of buttons in tkinter?

PythonButtonGridTkinterAutoresize

Python Problem Overview


I am trying to create a grid of buttons(in order to achieve the clickable cell effect) with Tkinter.

My main problem is that I cannot make the grid and the buttons autoresize and fit the parent window.

For example, when I have a high number of buttons on the grid, instead of shrinking the buttons so that the grid fits inside the window, I get a stretched frame that goes off screen.

The effect that I am looking for is the grid filling all available space, then resizing its cells to fit within that space. I have read at the documentation, but I still cannot figure out how to make it work.

This is the basic code which is my starting point:

def __init__(self):
    root = Tk()
    frame = Frame(root)
    frame.grid()
    
    #some widgets get added in the first 6 rows of the frame's grid          
    
    #initialize grid
    grid = Frame(frame)  
    grid.grid(sticky=N+S+E+W, column=0, row=7, columnspan=2)

    #example values
    for x in range(60):
        for y in range(30):
            btn = Button(grid)
            btn.grid(column=x, row=y)
    
    root.mainloop()

Python Solutions


Solution 1 - Python

You need to configure the rows and columns to have a non-zero weight so that they will take up the extra space:

grid.columnconfigure(tuple(range(60)), weight=1)
grid.rowconfigure(tuple(range(30)), weight=1)

You also need to configure your buttons so that they will expand to fill the cell:

btn.grid(column=x, row=y, sticky="news")

This has to be done all the way up, so here is a full example:

from tkinter import *

root = Tk()
frame = Frame(root)
root.rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)
frame.grid(row=0, column=0, sticky="news")
grid = Frame(frame)
grid.grid(sticky="news", column=0, row=7, columnspan=2)
frame.rowconfigure(7, weight=1)
frame.columnconfigure(0, weight=1)

#example values
for x in range(10):
    for y in range(5):
        btn = Button(frame)
        btn.grid(column=x, row=y, sticky="news")

frame.columnconfigure(tuple(range(10)), weight=1)
frame.rowconfigure(tuple(range(5)), weight=1)

root.mainloop()

Solution 2 - Python

@Vaughn Cato gave an excellent answer here. However, he has accidentally included a bunch of extraneous code in his example. Here is a cleaned up and more organized full example doing exactly what his example does.

from tkinter import *

#Create & Configure root 
root = Tk()
Grid.rowconfigure(root, 0, weight=1)
Grid.columnconfigure(root, 0, weight=1)

#Create & Configure frame 
frame=Frame(root)
frame.grid(row=0, column=0, sticky=N+S+E+W)

#Create a 5x10 (rows x columns) grid of buttons inside the frame
for row_index in range(5):
    Grid.rowconfigure(frame, row_index, weight=1)
    for col_index in range(10):
        Grid.columnconfigure(frame, col_index, weight=1)
        btn = Button(frame) #create a button inside frame 
        btn.grid(row=row_index, column=col_index, sticky=N+S+E+W)  

root.mainloop()

Screenshots:

When it first opens (small):

enter image description here

After you maximize the window:

enter image description here

Solution 3 - Python

To make the buttons expand when the window is maximized, try to modify the button.grid entry as follows:

btn.grid(column=x, row=y, sticky=N+S+E+W)

Solution 4 - Python

The grid weight method might not work when you use scrollbar (at least in Mac) , so while using it pack the widget and scrollbar inside a frame and then grid the frame instead.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKirilView Question on Stackoverflow
Solution 1 - PythonVaughn CatoView Answer on Stackoverflow
Solution 2 - PythonGabriel StaplesView Answer on Stackoverflow
Solution 3 - PythonTony WaiteView Answer on Stackoverflow
Solution 4 - PythonSanjayView Answer on Stackoverflow