tkinter 网格布局和标签高度

tkinter grid layout and label hight

我有一个输入表单(在其他小部件中)有一个 Entry 小部件用于输入一些值,还有一个 Listbox 用于显示目前输入的有效值。在 Entry 小部件下方,我显示了一条验证消息(当值有效时为空,否则为错误描述)以及一个大符号('' 表示错误,'' 表示有效)。

以下是通过单击按钮模拟有效和无效条目的最小示例:

import tkinter as tk

root = tk.Tk()

tk.Entry(root).grid(column=0, row=0, sticky=tk.N)
tk.Listbox(root, height=10).grid(column=1, row=0, rowspan=3, sticky=tk.N)

label = tk.Label(root)
label.grid(column=0, row=1, sticky=tk.N)

symbol = tk.Label(root, font='Arial 72 bold')
symbol.grid(column=0, row=2, sticky=tk.S)

def toggle():
    n = 0 if len(label['text']) > 10 else 3
    label['text'] = '\n'.join([f'error message line {i}' for i in range(n)])
    symbol['text'] = '' if n else ''
        
tk.Button(root, text='toggle message', command=toggle).grid(column=0, row=3)

root.mainloop()

当错误消息变长时,符号会向下移动,尽管最后一个错误消息行的底部和符号顶部之间仍然有很多 space。原因是 72 pt 字体的最大字符高度可以使用这个额外的 space(可以通过在符号前插入一个完整的高度垂直线 来轻松验证。

除了减小符号字体大小(我不想要)或增加为消息和符号保留的总高度(我不能)之外,我看到唯一的解决方法是将字符符号替换为一个图像符号,其中笔划延伸到整个图像高度。

所以我的问题是:如何在消息行高度改变时将按钮保持在原位?是否有可能以某种方式重叠符号和消息(知道符号字符笔画不会填满整个字体高度)。我尝试了负填充,但 tkinter 不允许这样做。我还想坚持使用 grid 布局管理器。

通过调整第二行的大小以适应 window 高度并将 grid_propagate 设置为 False,然后按钮保持原位:

import tkinter as tk

root = tk.Tk()

tk.Entry(root).grid(column=0, row=0, sticky=tk.N)
tk.Listbox(root, height=10).grid(column=1, row=0, rowspan=3, sticky=tk.N)

root.rowconfigure(2, weight=1)  # make second row resize to fit window height 
label = tk.Label(root)
label.grid(column=0, row=1, sticky=tk.N)

symbol = tk.Label(root, font='Arial 72 bold')
symbol.grid(column=0, row=2, sticky=tk.S)

def toggle():
    n = 0 if len(label['text']) > 10 else 3
    label['text'] = '\n'.join([f'error message line {i}' for i in range(n)])
    symbol['text'] = '' if n else ''

tk.Button(root, text='toggle message', command=toggle).grid(column=0, row=3)
root.update_idletasks()
root.grid_propagate(False)  # disable window resizing when its children change size
root.mainloop()

请注意,如果错误消息很长,则符号将不可见。