如何使用 tkinter 和 pack 在 python 中调整具有框架的 window 大小时冻结窗格?

How to Freeze a pane while re-sizing a window that has frames in python using tkinter and pack?

这是我在 Whosebug 上的第一个 post。我终于 posting 因为我在任何地方都找不到这个并且已经搜索了将近 4 个小时,但我被卡住了。

这是我的代码示例:

import tkinter as tk
from tkinter import *
root = tk.Tk()
root.geometry("600x100+200+200")
leftverticalFrame = Frame(root)
leftverticalFrame.pack(side=LEFT)
middleverticlFrame = Frame(root)
middleverticlFrame.pack(expand=TRUE)
rightverticalFrame = Frame(root)
rightverticalFrame.pack(side=RIGHT)

right = tk.Label(rightverticalFrame, text="Right Vertical Status Frame", bg="yellow")
right.pack(side=tk.RIGHT, fill=BOTH)

left = tk.Label(leftverticalFrame, text = "Left Vertical Navigation Frame", bg="orange")
left.pack(side=tk.LEFT, fill=BOTH)

bottom = tk.Label(middleverticlFrame, text="Middle Vertical Frame", bg="blue")
bottom.pack(side=tk.BOTTOM, expand=True, fill=tk.BOTH)

root.mainloop()

我所做的只是尝试在根目录中单独布置框架,因为框架将使用不同的管理器。左框架的功能完全符合我的要求,中间框架也是如此。问题出在右边的框架上。

请注意,当您调整 window 的大小使其更窄时,右侧的框架会进入 "middle frame's territory"。现在奇怪的是,当涉及到左框架的边界时,中间框架不会复制相同的行为。我希望右框架的行为与中间框架相同。本质上,我试图让左和右相当静态,但中间框架更动态。谁能告诉我我做错了什么?

关于 pack 需要记住的一件重要事情是 side 属性不是指 window 的那一边,它指的是 的那一边剩余可用 space。这导致你打包东西的顺序和你打包它们的一侧很重要,因为每次你打包东西你都会改变位置和剩余可用的数量 space。

在这种情况下,问题是您没有为中间框架指定 side 属性,因此它默认为 "top"(如 "top of the remaining space"、不是 "top of the window")。因为左边已经有东西了,所以这会把它放在右边剩余的 space 的顶部。然后,当你把下一个项目放在右边时,它在右边但在顶部的东西下面。

至少有几种方法可以解决这个问题。第一种是先包左右两边,再包中间。在这种情况下,你把中框放在哪边都没有关系:

leftverticalFrame.pack(side=LEFT)
rightverticalFrame.pack(side=RIGHT)
middleverticlFrame.pack(expand=TRUE, side=TOP)

第二个解决方案是保留它们的原始顺序,但将中间框架放在左侧或右侧而不是顶部:

leftverticalFrame.pack(side=LEFT)
middleverticlFrame.pack(expand=TRUE, side=LEFT)
rightverticalFrame.pack(side=RIGHT)

这两个变体最初看起来是相同的,或者可能几乎相同,这取决于框架或 window 中的其他内容。但是,当您开始使 window 太小而无法容纳所有帧时,行为会有所不同。

在这种情况下,tkinter 最终必须开始减小小部件的大小。它以与打包相反的顺序执行此操作(读作:最后打包的是第一个收缩的)。也就是说,如果你想让左右两边尽量固定的话,最后把中间那段包起来。


专业提示:如果您将所有布局代码组合在一起,您的代码将更易于阅读和维护。考虑这段代码:

f1 = Frame(...)
f1.pack(...)
f2 = Frame(...)
f2.pack(...)

我认为随着时间的推移您会发现,如果您这样编写代码,您的代码将更易于阅读和维护:

f1 = Frame(...)
f2 = Frame(...)
...
f1.pack(...)
f2.pack(...)
...

我认为它使代码更容易可视化,因为给定父级 window 的所有布局都在一个地方,而不是散布在整个代码中。