使用框架和网格的tkinter gui布局

时间:2015-12-14 21:10:59

标签: python layout tkinter frame

我的gui layout

gui layout

看起来几乎不像what I expect

what I expect

所以我假设有些基础知识我不明白。

我认为框架包含自己的网格空间' (行,列)但我看到的行为并不能解决这个问题,而且我不知道如何让事情按照我想要的方式进行。我的标签应该放在同一行L到R上,在一个框架标签下面。横跨整个框架 - 除了他们不是。我希望实际看起来更像目标jpg,我想用网格来做它。

您可以看到绿框右侧的其中一个输入字段。它为什么要去那里?

from Tkinter import *

root = Tk()
root.title('Model Definition')
root.resizable(width=FALSE, height=FALSE)
root.geometry('{}x{}'.format(460, 350))

top_frame = Frame(root, bg='cyan', width = 450, height=50, pady=3).grid(row=0, columnspan=3)
Label(top_frame, text = 'Model Dimensions').grid(row = 0, columnspan = 3)
Label(top_frame, text = 'Width:').grid(row = 1, column = 0)
Label(top_frame, text = 'Length:').grid(row = 1, column = 2)
entry_W = Entry(top_frame).grid(row = 1, column = 1)
entry_L = Entry(top_frame).grid(row = 1, column = 3)
#Label(top_frame, text = '').grid(row = 2, column = 2)

center = Frame(root, bg='gray2', width=50, height=40, padx=3, pady=3).grid(row=1, columnspan=3)
ctr_left = Frame(center, bg='blue', width=100, height=190).grid(column = 0, row = 1, rowspan = 2)
ctr_mid = Frame(center, bg='yellow', width=250, height=190, padx=3, pady=3).grid(column = 1, row=1, rowspan=2)
ctr_right = Frame(center, bg='green', width=100, height=190, padx=3, pady=3).grid(column = 2, row=1, rowspan=2)

btm_frame = Frame(root, bg='white', width = 450, height = 45, pady=3).grid(row = 3, columnspan = 3)
btm_frame2 = Frame(root, bg='lavender', width = 450, height = 60, pady=3).grid(row = 4, columnspan = 3)


root.mainloop()

具体来说,我的标签和Entry小部件在哪里,以及如何让它们看起来更像目标(顶部框架,其余部分用于以后)。

2 个答案:

答案 0 :(得分:30)

  

我认为帧包含自己的“网格空间”

这是一个正确的假设。

  

您可以看到绿色右侧的其中一个输入字段   帧。它为什么要去那里?

问题从这里开始:

top_frame = Frame(root, ...).grid(row=0, ...)

在python中,x = y().z()始终将x设置为.z()的结果。在top_frame = Frame(...).grid(...)的情况下,grid(...)始终返回None,因此top_frame将为None。这会导致您认为进入顶部框架的每个窗口小部件实际进入根窗口。

解决方案概述

作为一般经验法则,您应该从不调用gridpackplace作为创建窗口小部件的同一语句的一部分。部分原因是您遇到的这种确切行为,但也因为我认为这会使您的代码更难以编写,并且随着时间的推移难以维护。

窗口小部件创建和窗口小部件布局是两回事。根据我的经验,当您将布局命令组合在一起时,布局问题相当更容易调试。

此外,在使用网格时应保持一致,并始终以相同的顺序放置选项,以便您可以更轻松地显示布局。最后,当使用grid时,您应该养成始终指定sticky选项的习惯,并始终在每个包含框架中给出一行和一列非零权重。

解决方案示例

以下是我编写代码的方法。它更长,但更容易理解。

from Tkinter import *

root = Tk()
root.title('Model Definition')
root.geometry('{}x{}'.format(460, 350))

# create all of the main containers
top_frame = Frame(root, bg='cyan', width=450, height=50, pady=3)
center = Frame(root, bg='gray2', width=50, height=40, padx=3, pady=3)
btm_frame = Frame(root, bg='white', width=450, height=45, pady=3)
btm_frame2 = Frame(root, bg='lavender', width=450, height=60, pady=3)

# layout all of the main containers
root.grid_rowconfigure(1, weight=1)
root.grid_columnconfigure(0, weight=1)

top_frame.grid(row=0, sticky="ew")
center.grid(row=1, sticky="nsew")
btm_frame.grid(row=3, sticky="ew")
btm_frame2.grid(row=4, sticky="ew")

# create the widgets for the top frame
model_label = Label(top_frame, text='Model Dimensions')
width_label = Label(top_frame, text='Width:')
length_label = Label(top_frame, text='Length:')
entry_W = Entry(top_frame, background="pink")
entry_L = Entry(top_frame, background="orange")

# layout the widgets in the top frame
model_label.grid(row=0, columnspan=3)
width_label.grid(row=1, column=0)
length_label.grid(row=1, column=2)
entry_W.grid(row=1, column=1)
entry_L.grid(row=1, column=3)

# create the center widgets
center.grid_rowconfigure(0, weight=1)
center.grid_columnconfigure(1, weight=1)

ctr_left = Frame(center, bg='blue', width=100, height=190)
ctr_mid = Frame(center, bg='yellow', width=250, height=190, padx=3, pady=3)
ctr_right = Frame(center, bg='green', width=100, height=190, padx=3, pady=3)

ctr_left.grid(row=0, column=0, sticky="ns")
ctr_mid.grid(row=0, column=1, sticky="nsew")
ctr_right.grid(row=0, column=2, sticky="ns")

root.mainloop()

结果:

screenshot of running example

答案 1 :(得分:2)

variable = Widget(...).grid()None分配给变量,因为grid() / pack() / place()返回None

使用

variable = Widget(...)
variable.grid() # .pack() .place()