你需要使用grid_columnconfigure
给中间的列一些权重。由于比其他柱子重量更大,它们会膨胀和收缩以填充您拥有的任何额外空间。但是,就您而言,确实不需要使用网格。 GUI 中的所有内容都沿着特定的边对齐pack
是更自然的搭配。
我将展示如何使用 pack 和 grid,从 pack 开始,因为它是最简单的。即使你坚持使用grid
,通读下一节,了解如何将一个大的布局问题分解为许多较小的布局问题。
分而治之
在 Tkinter 中进行布局的最佳方法是“分而治之”。从最外面的小部件开始,并按照您想要的方式获取它们。然后,一次解决其中的每一个。
在您的情况下,您有一个最外面的小部件 - 主容器。由于它是窗口中唯一的小部件,因此 pack 是让它填充整个容器的最简单方法。您也可以使用网格,但它需要一些额外的工作:
self.main_container = Frame(parent. background="bisque")
self.main_container.pack(side="top", fill="both", expand=True)
它有助于暂时为您的相框赋予独特的颜色,以便您在冲洗时可以直观地看到它们。只需将上面的代码添加到您的__init__
,运行您的应用程序,然后调整窗口大小以查看主框架是否正确放大和缩小。
接下来,您有两个框架——top_frame 和bottom_frame。根据它们的名称并根据您尝试使用网格的方式来判断,我认为它们应该在 x 方向上填充 GUI。另外,我猜顶部框架是某种工具栏,底部框架是 GUI 的真正“主要”部分。因此,让我们让底部的小部件占据所有额外的空间。
由于这些是堆叠在一起的,pack
又是自然的选择。添加以下代码(并且仅添加以下代码),以确保这些区域占据您期望的窗口部分,并且它们具有正确的调整大小行为。
self.top_frame = Frame(self.main_container, background="green")
self.bottom_frame = Frame(self.main_container, background="yellow")
self.top_frame.pack(side="top", fill="x", expand=False)
self.bottom_frame.pack(side="bottom", fill="both", expand=True)
接下来是标签的框架。同样,它们占据了容器边缘的空间,因此pack
最有意义。再次,添加以下代码,运行程序,并确保内容仍然正确调整大小并填充窗口的正确部分:
self.top_left = Frame(self.top_frame, background="pink")
self.top_right = Frame(self.top_frame, background="blue")
self.top_left.pack(side="left", fill="x", expand=True)
self.top_right.pack(side="right", fill="x", expand=True)
接下来,您将获得“角落”标签。同样,由于容器只是一行小部件,pack
让一切变得简单。由于您希望标签位于角落,因此我们将设置sticky
每个属性略有不同:
self.top_left_label = Label(self.top_left, text="Top Left")
self.top_right_label = Label(self.top_right, text="Top Right")
self.top_left_label.pack(side="left")
self.top_right_label.pack(side="right")
最后,您就有了文本小部件。它填满了整个底部框架,所以再一次pack
是我们的朋友:
self.text_box = Text(self.bottom_frame, height=5, width=40, background="gray")
self.text_box.pack(side="top", fill="both", expand=True)
包还是网格?
您使用网格作为原始代码并询问如何修复它。为什么我在示例中使用 pack?
当你使用pack
,所有配置选项都可以包含在一次调用中。和grid
除了将小部件放入其容器中之外,您还必须注意为各个列和行赋予“权重”,以便它们正确调整大小。当您只是将小部件堆叠在一起或将它们排列成一行时,pack
使用起来更加方便。
在我的 GUI 中,我几乎总是结合使用grid
and pack
。他们都很强大,并且擅长不同的事情。唯一要记住的是——这是至关重要的-- 是你不能在同一个父级中使用它们。以您的代码为例,您不能使用pack
对于 top_left 框架和grid
对于 top_right 框架,因为它们共享相同的父级。你can但是,请在同一应用程序中混合使用它们。
再次,使用网格
好吧,也许你真的想用grid
:也许这是一项学校作业,或者也许您只想一次专注于一个几何管理器。这很酷。我就是这样做的。再次强调,你必须分而治之:
从主框架开始。将我们打包主容器的一条语句替换为以下几行。请注意,我们必须配置行和列parent,而不是我们创建的框架。
self.main_container.grid(row=0, column=0, sticky="nsew")
self.myParent.grid_rowconfigure(0, weight=1)
self.myParent.grid_columnconfigure(0, weight=1)
好的,现在是顶部和底部框架。去除pack
,并添加以下行。您仍然只有一列,但这次有几行。注意哪一行的权重为 1:
self.top_frame.grid(row=0, column=0, sticky="ew")
self.bottom_frame.grid(row=1, column=0,sticky="nsew")
self.main_container.grid_rowconfigure(1, weight=1)
self.main_container.grid_columnconfigure(0, weight=1)
角框——最后,一个有不止一根柱子的容器!让我们在中间创建第三列来填补所有的空白。更换pack
陈述如下,密切注意给予“权重”的内容:
self.top_left.grid(row=0, column=0, sticky="w")
self.top_right.grid(row=0, column=2, sticky="e")
self.top_frame.grid_columnconfigure(1, weight=1)
接下来是框架中的标签。由于我们不需要它们扩展,因此我们可以保留默认权重为零。您可能会觉得两个标签都在零列中很奇怪。请记住,它们位于不同的父级中,并且它们是其父级中唯一的小部件,因此每个小部件中只有一列:
self.top_left_label.grid(row=0, column=0, sticky="w")
self.top_right_label.grid(row=0, column=0, sticky="e")
最后我们有了文本小部件,它是底部框架中唯一的小部件。替换最后的pack
声明如下:
self.text_box.grid(row=0, column=0, sticky="nsew")
self.bottom_frame.grid_rowconfigure(0, weight=1)
self.bottom_frame.grid_columnconfigure(0, weight=1)
结论
布局小部件很容易,但您必须系统化。想想你在做什么,将你的小部件组织成组,然后一次处理一个组。当您这样做时,您应该使用哪个几何管理器应该变得很明显。
如你看到的,grid
需要多几行代码,但当您确实有网格时,这是正确的选择。在您的情况下,您已经将 GUI 细分为多个部分,因此即使最终结果是一个网格,每个部分要么包装在另一个部分的顶部或下方,要么包装在左侧或右侧边缘。在这些情况下,pack
使用起来更容易一些,因为您不必担心行和列的权重。