Why is there extra space after the last column in a Tkinter application?

Question:

I’m trying to build an application in Tkinter. When the user presses a button, I need 3 widgets to appear in certain rows and columns. When the user clicks again, I need 3 more widgets (of the same types) to appear to the right of the first ones. Do this until 5 widgets are on a row, then go to the next row. I managed to determine exactly where I want them to appear, but I can’t explain to myself why there’s some extra space after the last column, but not before the first one.

import tkinter as tk
import customtkinter
from tkinter import messagebox

root = tk.Tk()

root.minsize(1100, 650)
root.iconbitmap('textures/logo.ico')
root.title('Diceware')

global number_of_dicerolls
number_of_dicerolls = 0

# Give a weight to rows 0 to 15
i = 0
while i <= 15:
    root.grid_rowconfigure(i, weight=1, uniform='row')
    i += 1

# Give a weight to columns 0 to 9
i = 0
while i <= 9:
    root.grid_columnconfigure(i, weight=1, uniform='column')
    i += 1


def display_words():
    """
    Called when the user clicks the 'roll dice' button,
    this function displays the pairs of dice rolls and words to the user.
    """
    global number_of_dicerolls
    if number_of_dicerolls < 35:
        column_to_be_placed_in = (number_of_dicerolls % 5) * 2
        number_of_dicerolls += 1

        diceroll_widget = customtkinter.CTkTextbox(root, height=1)
        diceroll_widget.insert('1.0', 'Hello, world!')
        diceroll_widget.grid(row=2 + 2 * ((number_of_dicerolls - 1) // 5),
                             column=column_to_be_placed_in,
                             pady=(5, 0), padx=10)

        word_widget = customtkinter.CTkTextbox(root, height=1)
        word_widget.insert('1.0', 'Goodbye, world!')
        word_widget.grid(row=3 + 2 * ((number_of_dicerolls - 1) // 5),
                         column=column_to_be_placed_in,
                         sticky='n', pady=(0, 5), padx=10)

        test_var = tk.IntVar()
        checkbox = customtkinter.CTkCheckBox(master=root,
                                             variable=test_var, text='',
                                             checkbox_width=20,
                                             checkbox_height=20, fg_color='gray',
                                             hover_color='white')
        checkbox.grid(row=3 + 2 * ((number_of_dicerolls - 1) // 5),  column=column_to_be_placed_in + 1,
                      sticky='w')
    else:
        answer = tk.messagebox.askquestion('Dice roll limit reached',
                                           'You have reached the maximum limit of 35 dice rolls. Do you want '
                                           'to clear the screen?', parent=root)
        if answer == 'yes':
            clear_window()


roll_dice_button = customtkinter.CTkButton(root, border_width=2, border_color='black', text='ROLL DICE',
                                           fg_color='blue', hover_color='gray',
                                           command=display_words)
roll_dice_button.grid(row=0, column=0, columnspan=10, pady=0, sticky='n')

root.mainloop()

I tried adding some sticky attributes to the widgets, I tried messing around with the weight of the columns and rows, I tried removing the uniform attriburtes of the rows and columns in an attempt to solve this issue, I tried specifically setting padx, pady, ipadx and ipady to 0, but to no avail. The widgets moved around as expected (the checkboxes weren’t sticked to the west when I removed the ‘sticky’ attribute, for example), but that space after the last column, but not before the first one, remained.

Asked By: IceTheDev2

||

Answers:

The main problem is because of this code:

i = 0
while i <= 9:
    root.grid_columnconfigure(i, weight=1, uniform='column')
    i += 1

You’re forcing columns 0-9 to all be the same width. That means that the small checkbutton in columns 1, 3, 5, 7, and 9 will all be the same width as the columns with the text widgets. However, the checkbutton itself is visually smaller, so you end up with a lot of extra unused space to the right of the checkbutton.

One solution is to configure the columns differently, so that all of the text widget columns are the same, and all of the checkbutton columns are the same, but the two sets of columns are different widths.

root.grid_columnconfigure((0, 2, 4, 6, 8), weight=1, uniform="a")
root.grid_columnconfigure((1, 3, 5, 7, 9), uniform="b")

Also, since you’re not displaying text in the checkbuttons, you should probably set the width to zero so that there’s not a lot of unused space to the right of the checkbutton.

checkbox = customtkinter.CTkCheckBox(..., width=0, ...)

I also recommend giving a sticky value of "ew" to the text widgets so that they fill the column.

diceroll_widget.grid(..., sticky="ew")
word_widget.grid(..., sticky="ew")

screenshot

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.