dan*_*451 5 python layout tkinter
我正在构建一个软件的GUI,并希望实现这一目标:
######################################
# | some title #
# menu upper |----------------------#
# | #
# | CANVAS #
# menu lower | #
# | #
#------------------------------------#
# statusbar #
######################################
Run Code Online (Sandbox Code Playgroud)
菜单上部具有一些高级功能,菜单下限根据用户输入而变化.状态栏经常更改其内容.
不幸的是,Tkinter拒绝工作.
使用网格布局管理器我无法创建稳定的设计,并在左侧的菜单中添加标签和按钮等内容:
self.root = tk.Tk()
self.root.resizable(width=0, height=0)
self.root.title("some application")
# menu left
self.menu_left = tk.Frame(self.root, width=150, bg="#ababab")
self.menu_left.grid(row=0, column=0, rowspan=2, sticky="ns")
self.menu_left_upper = tk.Frame(self.menu_left, width=150, height=150, bg="red")
self.menu_left_upper.grid(row=0, column=0)
# this label breaks the design
#self.test = tk.Label(self.menu_left_upper, text="test")
#self.test.pack()
self.menu_left_lower = tk.Frame(self.menu_left, width=150, bg="blue")
self.menu_left_lower.grid(row=1, column=0)
# right area
self.some_title_frame = tk.Frame(self.root, bg="#dfdfdf")
self.some_title_frame.grid(row=0, column=1, sticky="we")
self.some_title = tk.Label(self.some_title_frame, text="some title", bg="#dfdfdf")
self.some_title.pack()
self.canvas_area = tk.Canvas(self.root, width=500, height=400, background="#ffffff")
self.canvas_area.grid(row=1, column=1)
self.root.mainloop()
Run Code Online (Sandbox Code Playgroud)
这种设计在左侧的菜单中没有内容.每当我添加一些东西self.menu_left_upper或者self.menu_left_lower像test标签一样,我的设计就破了:菜单框架消失了.另外,即使有了柱子,我也不得不删除状态栏,因为当它被添加时,左边的菜单再次消失了.
使用包布局管理器我得到了这个:
######################################
# | some title #
# |----------------------#
# menu upper | #
# | CANVAS #
# | #
# menu lower | #
# |----------------------#
# | statusbar #
######################################
Run Code Online (Sandbox Code Playgroud)
因为我希望左边的菜单框架消耗完整的y空间,所以我使用它pack(side="left", expand=True, fill="both"),但是这个设置总是拒绝状态栏去寻找全宽.
此外,纯包管理器代码看起来"丑陋".我认为使用网格管理器的设计更"清晰".因此我认为网格布局中的网格或包布局会很好吗?
有人可以帮忙吗?我陷入了GUI-hell:/
Bry*_*ley 12
做布局的关键是有条不紊,并使用正确的工具来完成工作.这也意味着有时你需要有创意.这意味着grid在铺设东西时使用
grid,并pack在从上到下或从左到右铺设时使用.
另一个关键是将布局代码组合在一起.当它在一个代码块中时,可视化和修改布局要容易得多.
在您的情况下,您似乎有三个或四个不同的区域,具体取决于您的计算方式.如果要使用grid,最简单的方法是将"菜单上部"和"菜单下部"组合到一个框架中,并将整个框架视为表格单元格.看起来你已经在做了,这很好.
那么,让我们从这些主要领域开始:
self.menu_left.grid(row=0, column=0, rowspan=2, sticky="nsew")
self.some_title_frame.grid(row=0, column=1, sticky="ew")
self.canvas_area.grid(row=1, column=1, sticky="nsew")
# you don't have a status bar in the example code, but if you
# did, this is where you would put it
# self.status_frame.grid(row=2, column=0, columnspan=2, sticky="ew")
Run Code Online (Sandbox Code Playgroud)
无论grid何时使用,您都需要为至少一行和一列提供正权重,以便tkinter知道在哪里使用任何未分配的空间.通常有一个小部件是"主"小部件.在这种情况下,它是画布.您希望确保画布的行和列的权重为1(一):
self.root.grid_rowconfigure(1, weight=1)
self.root.grid_columnconfigure(1, weight=1)
Run Code Online (Sandbox Code Playgroud)
注意:使用pack而不是grid会保存两行代码,因为pack不需要你按照方式设置权重grid.
接下来,我们需要解决菜单区域的问题.默认情况下,框架会缩小以适合其内容,这就是添加标签会破坏布局的原因.你没有告诉tkinter如何处理额外的空间,所以框架缩小以适应,并且额外的空间未被使用.
由于您希望每个共享该区域50%的"menu_upper"和"menu_lower",这pack是最简单的解决方案.您可以使用grid,但它需要更多行代码来添加行和列权重.
self.menu_left_upper.pack(side="top", fill="both", expand=True)
self.menu_left_lower.pack(side="top", fill="both", expand=True)
Run Code Online (Sandbox Code Playgroud)
这是一个功能正常的版本,带有状态栏.请注意它在调整窗口大小时的行为方式:
import Tkinter as tk
class Example():
def __init__(self):
self.root = tk.Tk()
self.root.title("some application")
# menu left
self.menu_left = tk.Frame(self.root, width=150, bg="#ababab")
self.menu_left_upper = tk.Frame(self.menu_left, width=150, height=150, bg="red")
self.menu_left_lower = tk.Frame(self.menu_left, width=150, bg="blue")
self.test = tk.Label(self.menu_left_upper, text="test")
self.test.pack()
self.menu_left_upper.pack(side="top", fill="both", expand=True)
self.menu_left_lower.pack(side="top", fill="both", expand=True)
# right area
self.some_title_frame = tk.Frame(self.root, bg="#dfdfdf")
self.some_title = tk.Label(self.some_title_frame, text="some title", bg="#dfdfdf")
self.some_title.pack()
self.canvas_area = tk.Canvas(self.root, width=500, height=400, background="#ffffff")
self.canvas_area.grid(row=1, column=1)
# status bar
self.status_frame = tk.Frame(self.root)
self.status = tk.Label(self.status_frame, text="this is the status bar")
self.status.pack(fill="both", expand=True)
self.menu_left.grid(row=0, column=0, rowspan=2, sticky="nsew")
self.some_title_frame.grid(row=0, column=1, sticky="ew")
self.canvas_area.grid(row=1, column=1, sticky="nsew")
self.status_frame.grid(row=2, column=0, columnspan=2, sticky="ew")
self.root.grid_rowconfigure(1, weight=1)
self.root.grid_columnconfigure(1, weight=1)
self.root.mainloop()
Example()
Run Code Online (Sandbox Code Playgroud)
在一个不相关的说明:我强烈建议您不要删除用户调整窗口大小的能力.他们比你更了解他们的要求.如果你使用grid和pack不当,图形用户界面将完全重新调整.