我正在尝试创建两个Label小部件,这些小部件位于我的测试用户界面的左上角和右上角。问题是小部件被粘在一起,我希望它们之间有空间。
在我的研究中,我遇到了使用粘性,padx和pady选项的建议。但无论我传递给.grid()的参数是什么,我似乎都无法在我的小部件之间创建空间。我知道无论两个小部件之间的列和行数是多少,如果所说的行/列都是空的,那么就好像它们不存在并且小部件看起来粘在一起。
使用.grid()方法,如何定位小部件以使它们不会粘在一起?
到目前为止,这是我的代码:
#!/usr/bin/python
from Tkinter import *
class MyApp:
def __init__(self, parent):
self.myParent = parent
self.main_container = Frame(parent)
self.main_container.grid(row=0, rowspan=2, column=0, columnspan=4)
self.top_frame = Frame(self.main_container)
self.top_frame.grid(row=0, column=0, columnspan=4)
self.top_left = Frame(self.top_frame)
self.top_left.grid(row=0, column=0, columnspan=2)
self.top_right = Frame(self.top_frame)
self.top_right.grid(row=0, column=2, columnspan=2)
self.bottom_frame = Frame(self.main_container)
self.bottom_frame.grid(row=2, column=0, columnspan=4)
self.top_left_label = Label(self.top_left, text="Top Left")
self.top_left_label.grid(row=0, column=0, sticky='W', padx=2, pady=2)
self.top_right_label = Label(self.top_right, text="Top Right")
self.top_right_label.grid(row=0, column=4, sticky='E', padx=2, pady=2)
self.text_box = Text(self.bottom_frame, height=5, width=40)
self.text_box.grid(row=0, column=0)
root = Tk()
root.title("Test UI")
myapp = MyApp(root)
root.mainloop()
〜〜更新〜〜
我尝试了以下但是没有用:
self.top_left = Frame(self.top_frame)
self.top_left.grid(row=0, column=0, columnspan=2)
for c in range(2):
self.top_left.columnconfigure(c, weight=2)
self.top_right = Frame(self.top_frame)
self.top_right.grid(row=0, column=2, columnspan=2)
for c in range(2):
self.top_right.columnconfigure(c, weight=2)
答案 0 :(得分:65)
您需要使用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)
接下来,你有#34;角落"标签。同样,由于容器只是一行小部件,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
并将小部件放入容器中时,您还必须注意提供各种列和行" weight"这样他们就可以正常调整大小。当您只是将小部件堆叠在一起或将它们排成一行时,pack
更容易使用。
在我的GUI中,我几乎总是使用grid
和pack
的组合。它们既强大又擅长于不同的事物。唯一要记住的是 - ,这是至关重要的 - 是你不能在同一个父母中使用它们。以您的代码为例,您不能将pack
用于top_left框架而grid
用于top_right框架,因为它们都共享同一个父框架。但 可以在同一个应用程序中混合它们。
好吧,也许你真的想要使用grid
:也许这是一个学校作业,或者你可能只想一次关注一个几何管理器。太酷了。这是我将如何做到的。再一次,你必须分而治之:
从主框架开始。用以下行替换我们打包主容器的一个语句。请注意,我们必须在父上配置行和列,而不是我们创建的帧。
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
语句替换为以下内容,密切关注所给出的内容" weight":
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
更容易使用,因为您不必担心行和列权重。
答案 1 :(得分:1)
如果您向bg = "red"
和top_left
个构建器添加top_right
,您会看到Frames
如何卡在中心,即使使用sticky
选项。如果它们不包含除单个小部件之外的任何内容,我建议不要使用它们。
#!/usr/bin/python
from Tkinter import *
class MyApp:
def __init__(self, parent):
self.top_left_label = Label(parent, text="Top Left")
self.top_left_label.grid(row=0, column=0, padx=2, pady=2, sticky=N+S+W)
self.top_right_label = Label(parent, text="Top Right")
self.top_right_label.grid(row=0, column=1, padx=2, pady=2, sticky=N+S+E)
self.text_box = Text(parent, height=5, width=40)
self.text_box.grid(row=1, column=0, columnspan=2)
root = Tk()
root.title("Test UI")
myapp = MyApp(root)
root.mainloop()
答案 2 :(得分:1)
这是一种简单的方法:
答案 3 :(得分:1)
Tkinter的“网格”想把所有东西放在一起。这就是为什么你不能跳过细胞。您必须指定宽度,然后锚定文本。我添加了颜色来帮助展示细胞。我把bd放在框架中。然后我必须给左右两侧的细胞赋予宽度,这样网格就会给它们带来重量。然后锚文本西或东。我不知道为什么我必须为每个单元格添加额外的2个空格,但我认为这是一个字体问题。
我相信Rodas更清洁,更简单,但我试图保持在您询问的参数范围内。
对于小东西来说,包装更容易,更快。
from tkinter import *
class MyApp:
def __init__(self, parent):
self.myParent = parent
self.main_container = Frame(parent, bg="green")
self.main_container.grid()
self.top_frame = Frame(self.main_container)
self.top_frame.grid()
self.top_left = Frame(self.top_frame, bd=2)
self.top_left.grid(row=0, column=0)
self.top_right = Frame(self.top_frame, bd=2)
self.top_right.grid(row=0, column=2)
self.top_left_label = Label(self.top_left, bd=2, bg="red", text="Top Left", width=22, anchor=W)
self.top_left_label.grid(row=0, column=0)
self.top_right_label = Label(self.top_right, bd=2, bg="blue", text="Top Right", width=22, anchor=E)
self.top_right_label.grid(row=0, column=0)
self.bottom_frame = Frame(self.main_container, bd=2)
self.bottom_frame.grid(row=2, column=0)
self.text_box = Text(self.bottom_frame, width=40, height=5)
self.text_box.grid(row=0, column=0)
root = Tk()
root.title("Test UI")
myapp = MyApp(root)
root.mainloop()
答案 4 :(得分:0)
如果您需要完全控制gui组件的位置,请尝试布局;一种高度可管理的方法是在几个框架中组织您的组件,每个框架都有网格或包布局,然后使用场所布局组织所有这些框架。