嵌套布局中按钮无法随所在底层框架拉伸的问题排查
最小可复现示例(MRE)
import tkinter as tk from tkinter import ttk root = tk.Tk() root.geometry("300x200") style = ttk.Style() mainframe = ttk.Frame(root) frame = ttk.Frame(mainframe) label = ttk.Label(frame, text="Lorem ipsum dolor sit amet") frame2 = ttk.Frame(mainframe, style="debug.TFrame") button2 = ttk.Button(frame2, text="Button22222") mainframe.grid() frame.grid() label.grid() frame2.grid(sticky="we") button2.grid(sticky="we") # frame2.columnconfigure(0, weight=1) style.configure("debug.TFrame", background="red") root.mainloop()
(注:原代码缺少import tkinter as tk,已补充以保证可运行)
问题与解答
为何按钮设置
sticky="we"却无法拉伸,但frame2已拉伸至标签宽度?sticky="we"的作用是让组件填充所在的网格单元格,但前提是单元格本身有可填充的额外宽度。frame2通过sticky="we"拉伸到了mainframe的宽度,但frame2内部的第0列默认weight=0——这意味着该列不会分配任何额外空间,按钮所在的单元格宽度就是按钮自身的最小宽度,没有多余空间让按钮拉伸,所以即便设置了sticky也没用。为何按钮会丢失内边距?
这是因为按钮所在的单元格宽度刚好等于按钮的最小显示宽度,sticky="we"让按钮填满了单元格,但此时按钮的文字已经占满了所有可用空间,内边距被挤压得完全看不见。如果单元格有多余宽度,按钮拉伸后,文字周围的内边距会正常显示。为何
frame2.columnconfigure(0, weight=1)能解决问题?columnconfigure的weight参数用于指定容器有额外空间时,对应列分配空间的比例。给frame2的第0列设置weight=1后,该列会接收frame2所有的额外宽度空间,按钮所在的单元格就会被撑到frame2的整个宽度。此时按钮的sticky="we"就能让它填满整个单元格,自然拉伸到frame2的宽度。
你之前认为columnconfigure仅用于分配额外空间,这个理解是对的——这里frame2本身已经有了额外空间(它被拉伸到了标签的宽度,远大于按钮的最小宽度),设置weight=1就是把这些额外空间全部分配给第0列,让按钮所在的单元格能容纳按钮拉伸。
内容的提问来源于stack exchange,提问作者gomd

