英文:
Why is there extra space after the last column in a Tkinter application?
问题
我正在尝试使用Tkinter构建一个应用程序。当用户按下按钮时,我需要在特定的行和列中出现3个小部件。当用户再次单击时,我需要再次出现3个小部件(相同类型的),位于第一组小部件的右侧。重复此操作,直到一行上有5个小部件,然后进入下一行。我已经确定了它们出现的确切位置,但无法解释为什么在最后一列之后有一些额外的空白,但在第一列之前没有。
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
# 给0到15行设置权重
i = 0
while i <= 15:
root.grid_rowconfigure(i, weight=1, uniform='row')
i += 1
# 给0到9列设置权重
i = 0
while i <= 9:
root.grid_columnconfigure(i, weight=1, uniform='column')
i += 1
def display_words():
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()
我尝试向小部件添加一些sticky
属性,尝试调整列和行的权重,尝试在解决此问题时删除行和列的uniform
属性,尝试将padx
、pady
、ipadx
和ipady
明确设置为0,但都没有成功。小部件按预期移动(例如,当我删除'sticky'
属性时,复选框未粘附到西侧),但在最后一列之后有一些空白,但在第一列之前没有。
英文:
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.
答案1
得分: 1
以下是翻译的代码部分:
主要问题是因为这段代码:
i = 0
while i <= 9:
root.grid_columnconfigure(i, weight=1, uniform='column')
i += 1
你正在强制使列0到9都具有相同的宽度。这意味着列1、3、5、7和9中的小复选框将与文本小部件所在的列具有相同的宽度。然而,复选框本身在视觉上较小,因此在复选框右侧会有大量未使用的空间。
一个解决方案是不同配置列,使所有文本小部件列具有相同的宽度,而所有复选框列具有不同的宽度。
root.grid_columnconfigure((0, 2, 4, 6, 8), weight=1, uniform="a")
root.grid_columnconfigure((1, 3, 5, 7, 9), uniform="b")
此外,由于你并没有在复选框中显示文本,你应该将 width
设置为零,以便在复选框右侧没有大量未使用的空间。
checkbox = customtkinter.CTkCheckBox(..., width=0, ...)
我还建议为文本小部件设置 sticky
值为 "ew" 以填充列。
diceroll_widget.grid(..., sticky="ew")
word_widget.grid(..., sticky="ew")
英文:
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")
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论