英文:
Tkinter frames height and width not matching the full size of the main window
问题
import tkinter
class MainBox:
def __init__(self):
# 主窗口规格
self.root = tkinter.Tk()
self.root.title('实用工具箱')
self.root.geometry('700x450')
self.root.resizable(False, False)
self.root.configure(bg='red')
self.root.iconbitmap(r'D:\2xProjects\Python\UtilityBox\resources\appicon.ico')
self.window_already_open = False
# 操作框架(搜索、排序、删除、重命名等)
self.operations_frame = tkinter.Frame(self.root, width=700, height=350, bg='#293556')
self.operations_frame.grid(row=0, sticky='ew')
# 日志框架
# 用于记录操作结果(成功或失败)
# 例如:搜索:在指定路径中找到文件/文件
self.log_frame = tkinter.Frame(self.root, width=700, height=100, bg='#2E4583')
self.log_frame.grid(row=1, sticky='ew')
# 用户必须填写操作所需的搜索窗口
def search_details():
if not self.window_already_open:
self.window_already_open = True
search_window = tkinter.Toplevel()
search_window.title('搜索选项')
search_window.geometry('250x160')
search_window.resizable(False, False)
search_window.configure(bg='#293556')
file_path = tkinter.Label(search_window, width=35, wraplength=150)
file_path.grid(row=0, column=0, sticky='nw', padx=(15, 5), pady=(15, 0))
# 基于文件名搜索(例如:名称或名称.扩展)
file_name = tkinter.Label(search_window, width=35, wraplength=150)
file_name.grid(row=1, column=0, sticky='nw', padx=(15, 5), pady=(15, 0))
# 搜索具有关联扩展名的文件(例如:所有.txt文件)
extension = tkinter.Label(search_window, width=35, wraplength=150)
extension.grid(row=2, column=0, sticky='nw', padx=(15, 5), pady=(15, 0))
start_searching = tkinter.Button(search_window, text='开始搜索', bg='#294F63', fg='white')
start_searching.grid(row=4, column=0, sticky='nw', padx=15, pady=(15, 0))
def on_window_close():
self.window_already_open = False
search_window.destroy()
search_window.protocol("WM_DELETE_WINDOW", on_window_close)
# 搜索功能(按钮和功能描述)
search_option = tkinter.Button(self.operations_frame, text='搜索', bg='#294F63', fg='white',
command=search_details)
search_option.grid(row=0, column=0, sticky='nw', padx=15, pady=(15, 0))
search_description = tkinter.Label(self.operations_frame,
text='搜索描述')
search_description.grid(row=0, column=0, sticky='nw', padx=70, pady=(18, 0))
# 排序功能(按钮和功能描述)
sort_option = tkinter.Button(self.operations_frame, text='排序', bg='#294F63', fg='white')
sort_option.grid(row=1, column=0, sticky='nw', padx=15, pady=(5, 0))
sort_description = tkinter.Label(self.operations_frame,
text='排序描述')
sort_description.grid(row=1, column=0, sticky='nw', padx=55, pady=(7, 0))
# 删除功能(按钮和功能描述)
delete_option = tkinter.Button(self.operations_frame, text='删除', bg='#294F63', fg='white')
delete_option.grid(row=2, column=0, sticky='nw', padx=15, pady=(5, 0))
delete_description = tkinter.Label(self.operations_frame,
text='删除描述')
delete_description.grid(row=2, column=0, sticky='nw', padx=105, pady=(7, 0))
# 重命名功能(按钮和功能描述)
rename_option = tkinter.Button(self.operations_frame, text='重命名', bg='#294F63', fg='white')
rename_option.grid(row=3, column=0, sticky='nw', padx=15, pady=(5, 0))
rename_description = tkinter.Label(self.operations_frame,
text='重命名描述')
rename_description.grid(row=3, column=0, sticky='nw', padx=105, pady=(7, 0))
# 复制功能(按钮和功能描述)
duplication_option = tkinter.Button(self.operations_frame, text='复制', bg='#294F63', fg='white')
duplication_option.grid(row=4, column=0, sticky='nw', padx=15, pady=(5, 0))
duplication_description = tkinter.Label(self.operations_frame,
text='复制描述')
duplication_description.grid(row=4, column=0, sticky='nw', padx=105, pady=(7, 0))
# 权限功能(按钮和功能描述)
permissions_option = tkinter.Button(self.operations_frame, text='权限', bg='#294F63', fg='white')
permissions_option.grid(row=5, column=0, sticky='nw', padx=15, pady=(5, 0))
permissions_description = tkinter.Label(self.operations_frame,
text='权限描述')
permissions_description.grid(row=5, column=0, sticky='nw', padx=105, pady=(7, 0))
# 比较功能(按钮和功能描述)
compare_option = tkinter.Button(self.operations_frame, text='比较', bg='#294F63', fg='white')
compare_option.grid(row=6, column=0, sticky='nw', padx=15, pady=(5, 0))
compare_description = tkinter.Label(self.operations_frame,
text='比较描述')
compare_description.grid(row=6, column=0, sticky='nw', padx=105, pady=(7, 0))
# 预览功能(按钮和功能描述)
preview_option = tkinter.Button(self.operations_frame, text='预览', bg='#294F63', fg='white')
preview_option.grid(row=7, column=0, sticky='nw', padx=15, pady=(5, 0))
preview_description = tkinter.Label(self.operations_frame,
text='预览描述')
preview_description.grid(row=7, column=0, sticky='nw', padx=105, pady=(7, 0))
# 压缩/解压功能(按钮和功能描述)
compression_decompression_option = tkinter.Button(self.operations_frame, text='压缩/解压',
bg='#294F63', fg='white')
compression_decompression_option.grid(row=8, column=0, sticky='nw', padx=15, pady=(5, 0))
<details>
<summary>英文:</summary>
import tkinter
class MainBox:
def __init__(self):
# Main windows specifications
self.root = tkinter.Tk()
self.root.title(' Utility Box')
self.root.geometry('700x450')
self.root.resizable(False, False)
self.root.configure(bg='red')
self.root.iconbitmap(r'D:\2xProjects\Python\UtilityBox\resources\appicon.ico')
self.window_already_open = False
# Operations frame (search, sort, delete, rename etc)
self.operations_frame = tkinter.Frame(self.root, width=700, height=350, bg='#293556')
self.operations_frame.grid(row=0, sticky='ew')
# Log frame
# Will log the results of the operations (either success or failure)
# Ex search: found the file/ files in the specified path
self.log_frame = tkinter.Frame(self.root, width=700, height=100, bg='#2E4583')
self.log_frame.grid(row=1, sticky='ew')
# Search window where user must fill the details required for the operation to start
def search_details():
if not self.window_already_open:
self.window_already_open = True
search_window = tkinter.Toplevel()
search_window.title('Search options')
search_window.geometry('250x160')
search_window.resizable(False, False)
search_window.configure(bg='#293556')
file_path = tkinter.Label(search_window, width=35, wraplength=150)
file_path.grid(row=0, column=0, sticky='nw', padx=(15, 5), pady=(15, 0))
# Search based on the file name (ex: name or name.extension)
file_name = tkinter.Label(search_window, width=35, wraplength=150)
file_name.grid(row=1, column=0, sticky='nw', padx=(15, 5), pady=(15, 0))
# Search files with the associated extension (ex: all .txt files)
extension = tkinter.Label(search_window, width=35, wraplength=150)
extension.grid(row=2, column=0, sticky='nw', padx=(15, 5), pady=(15, 0))
start_searching = tkinter.Button(search_window, text='Start searching', bg='#294F63', fg='white')
start_searching.grid(row=4, column=0, sticky='nw', padx=15, pady=(15, 0))
def on_window_close():
self.window_already_open = False
search_window.destroy()
search_window.protocol("WM_DELETE_WINDOW", on_window_close)
# Search functionality (button and description of the functionality)
search_option = tkinter.Button(self.operations_frame, text='Search', bg='#294F63', fg='white',
command=search_details)
search_option.grid(row=0, column=0, sticky='nw', padx=15, pady=(15, 0))
search_description = tkinter.Label(self.operations_frame,
text='Search description')
search_description.grid(row=0, column=0, sticky='nw', padx=70, pady=(18, 0))
# Sort functionality (button and description of the functionality)
sort_option = tkinter.Button(self.operations_frame, text='Sort', bg='#294F63', fg='white')
sort_option.grid(row=1, column=0, sticky='nw', padx=15, pady=(5, 0))
sort_description = tkinter.Label(self.operations_frame,
text='Sort description')
sort_description.grid(row=1, column=0, sticky='nw', padx=55, pady=(7, 0))
# Delete functionality (button and description of the functionality)
delete_option = tkinter.Button(self.operations_frame, text='Delete', bg='#294F63', fg='white')
delete_option.grid(row=2, column=0, sticky='nw', padx=15, pady=(5, 0))
delete_description = tkinter.Label(self.operations_frame,
text='Delete description')
delete_description.grid(row=2, column=0, sticky='nw', padx=105, pady=(7, 0))
# Rename functionality (button and description of the functionality)
rename_option = tkinter.Button(self.operations_frame, text='Rename', bg='#294F63', fg='white')
rename_option.grid(row=3, column=0, sticky='nw', padx=15, pady=(5, 0))
rename_description = tkinter.Label(self.operations_frame,
text='Rename description')
rename_description.grid(row=3, column=0, sticky='nw', padx=105, pady=(7, 0))
# Duplication functionality (button and description of the functionality)
duplication_option = tkinter.Button(self.operations_frame, text='Duplication', bg='#294F63', fg='white')
duplication_option.grid(row=4, column=0, sticky='nw', padx=15, pady=(5, 0))
duplication_description = tkinter.Label(self.operations_frame,
text='Duplication description')
duplication_description.grid(row=4, column=0, sticky='nw', padx=105, pady=(7, 0))
# Permissions functionality (button and description of the functionality)
permissions_option = tkinter.Button(self.operations_frame, text='Permissions', bg='#294F63', fg='white')
permissions_option.grid(row=5, column=0, sticky='nw', padx=15, pady=(5, 0))
permissions_description = tkinter.Label(self.operations_frame,
text='Permissions description')
permissions_description.grid(row=5, column=0, sticky='nw', padx=105, pady=(7, 0))
# Compare functionality (button and description of the functionality)
compare_option = tkinter.Button(self.operations_frame, text='Compare', bg='#294F63', fg='white')
compare_option.grid(row=6, column=0, sticky='nw', padx=15, pady=(5, 0))
compare_description = tkinter.Label(self.operations_frame,
text='Compare description')
compare_description.grid(row=6, column=0, sticky='nw', padx=105, pady=(7, 0))
# Preview functionality (button and description of the functionality)
preview_option = tkinter.Button(self.operations_frame, text='Preview', bg='#294F63', fg='white')
preview_option.grid(row=7, column=0, sticky='nw', padx=15, pady=(5, 0))
preview_description = tkinter.Label(self.operations_frame,
text='Preview description')
preview_description.grid(row=7, column=0, sticky='nw', padx=105, pady=(7, 0))
# Compression/ decompression functionality (button and description of the functionality)
compression_decompression_option = tkinter.Button(self.operations_frame, text='Compression/ Decompression',
bg='#294F63', fg='white')
compression_decompression_option.grid(row=8, column=0, sticky='nw', padx=15, pady=(5, 0))
compression_decompression_description = tkinter.Label(self.operations_frame,
text='Compression/ decompression description')
compression_decompression_description.grid(row=8, column=0, sticky='nw', padx=205, pady=(7, 0))
# Window running loop
self.root.mainloop()
if __name__ == '__main__':
MainBox()
Hello!


I don't know how to fix the main window frames. I don't know if only the log frame is problematic or just there are multiple problems in multiple frames.
Operations frame (350) + log frame (100) = 450 - the full height of the root frame.
Why the dimensions are acting different than what I expected?
Also, I don't understand the span of the labels in the search window and why I can't enter anything when the window is active (I can't type anything in them).
Thank you in advance!
I've read the documentation but I can't figure it out.
I tried to modify the height mostly since in my logic that should be the issue, but with no success.
</details>
# 答案1
**得分**: 1
1. 如果您的框架都为空,则Math 350 + 100将起作用。但是,当您将其他小部件放入操作框架中(使用grid或pack方法),其高度将不再是350,而只能足够容纳其中的所有小部件(您可以看到,其高度刚好在compression_decompression_description标签之后结束)。了解更多信息 [在这里][1]。因此,如果要使框架的大小恒定,可以使用grid_propagate方法。因此,在创建框架后添加它:
self.operations_frame = tkinter.Frame(self.root, width=700,
height=350, bg='#293556')
self.operations_frame.grid_propagate(False)
self.operations_frame.grid(row=0, sticky='ew')
如果将在其他框架中创建子小部件,可以考虑采取相同的方法。
2. 标签的宽度不是以像素为单位测量的,而是以“字符”或文本单元为单位,其中一个单元通常等于零符号(0)的宽度。因此,宽度为35的标签大约可以容纳35个零。
3. 我是否正确理解您正在尝试在标签中输入内容?它们没有这样的功能。请改用Entry或Text小部件。
还可以改进的内容:
I. 在您的代码中,您可以使用继承,从Tk()根类中创建您的类,例如`class MainBox(tkinter.Tk)`。这可以使代码更清晰易读/理解。
II. 可能不必执行350+100,您可以使用rowconfigure并设置weight参数为1,例如。这将使框架占用所有可用空间。这将减少使用这样的数学计算的需要。因此,例如在root.configure之后添加以下内容:
self.root.resizable(False, False)
self.root.configure(bg='red')
self.root.rowconfigure(0, weight=1)
并将操作框架的sticky更改为“ewns”,例如`self.operations_frame.grid(row=0, sticky='ewns')`。通过使用此方法,您无需使用grid_propagate,也可以在不指定宽度和高度参数的情况下将框架留空,例如`self.operations_frame = tkinter.Frame(self.root, bg='#293556')`
III. 对于搜索窗口,我还会删除行`search_window.geometry('250x160')`。在我看来,如果窗口与其中的小部件匹配,那将更好,因此通过更改它们,窗口也将更改。这是可选的。
IV. 我不太喜欢您如何对齐“选项”和“描述”小部件。我认为最好创建一些额外的框架。看起来您试图从“Delete”到“preview”以相同的水平位置创建描述框架。因此,您可以为它们创建一个框架,然后只需将描述放入第一列即可。对于其余的小部件(搜索、排序和comp/decomp),可以为每个按钮+标签创建单独的框架,然后类似的操作。再次强调,这可以帮助减少对padx的数学计算或猜测。
[1]: https://stackoverflow.com/questions/45087645/why-are-frames-resizing-when-using-python-tkinter
<details>
<summary>英文:</summary>
1. Math 350 + 100 will work, if your frames are both empty. But when you put other widgets to the operations frame (using grid or pack methods), its height will become not 350, but just enough to fit all widgets in it (you can see, that its height finishes just after the compression_decompression_description label). Read more about this [there][1]. So, if you want to make frames size constant, you can use grid_propagate method. So add it after you've created the frame(s):
self.operations_frame = tkinter.Frame(self.root, width=700,
height=350, bg='#293556')
self.operations_frame.grid_propagate(False)
self.operations_frame.grid(row=0, sticky='ew')
maybe do the same thing for other frame, if you will create child widgets in it as well.
2. Labels width is measured not in pixels, but in "characters" or text units, which one unit is usually equal to the width of the zero symbol (0). so labels width of 35 could fit approximately 35 zeros.
3. Am l right that you are trying to enter something in labels? They have no such functionality. Use Entry or Text widgets instead please.
What could also be improved:
I. Use inheritance, in your code you can make your class from a Tk(), root class, like `class MainBox(tkinter.Tk)`. Makes code clearer and easier to read/understand.
II. Probably instead of doing 350+100, you could use rowconfigure with weight parameter to 1 for example. This will make frame occupy all available space. It will reduce the need of using such math. So add this after root.configure for example, like this:
self.root.resizable(False, False)
self.root.configure(bg='red')
self.root.rowconfigure(0, weight=1)
And change sticky of the operation frame to "ewns" so like `self.operations_frame.grid(row=0, sticky='ewns')`. By using this you don't need to use grid_propagate and also you can leave the frame without specifying width and height parameters, so `self.operations_frame = tkinter.Frame(self.root, bg='#293556')`
III. For the search window, I would also remove line `search_window.geometry('250x160')`. In my opinion it is better, if the window will match the widgets in it, so by changing them window will be changing as well. This is optional.
IV. I don't really like how you grid "option"s and "description"s widgets. I think it is better to create some extra frames. It seems that you are trying to make description frames from "Delete" to "preview" starts in the same horizontal position. So you can create a frame for them, and just put your descriptions in column 1. For the rest widgets (search, sort and comp/decomp) you can create a separate frames for each Button+Label, and then similar things. Again, this all can help to reduce math or guessing the numbers for padx.
[1]: https://stackoverflow.com/questions/45087645/why-are-frames-resizing-when-using-python-tkinter
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论