【问题标题】:tkinter gui layout using frames and grid使用框架和网格的 tkinter gui 布局
【发布时间】:2015-12-14 21:10:58
【问题描述】:

我的gui layout

看起来几乎不像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 小部件去了哪里,以及如何让它们看起来更像目标(顶部框架,其余部分留待以后使用)。

【问题讨论】:

  • 如果这两个图像使用相同的配色方案会有所帮助,除非它们是并且您说蓝色窗口确实应该在底部,即使代码将它放在左侧。

标签: python layout tkinter frame


【解决方案1】:

我假设框架包含自己的“网格空间”

这是一个正确的假设。

您只能看到绿色右侧的一个输入字段 框架。为什么要去那里?

问题从这里开始:

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

在 python 中,x = y().z() 将始终将x 设置为.z() 的结果。对于top_frame = Frame(...).grid(...),grid(...) 总是返回None,所以top_frame 将是None。这会导致您认为进入顶部框架的每个小部件实际上都进入根窗口。

解决方案概述

作为一般经验法则,您永远不应该在创建小部件的同一语句中调用 grid、pack 或 place。部分原因是您正在经历这种确切的行为,但也因为我认为随着时间的推移它会使您的代码更难编写和更难维护。

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

此外,您在使用grid 时应该保持一致,并且始终将选项按相同的顺序排列,这样您就可以更轻松地可视化布局。最后,在使用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()

结果:

【讨论】:

  • 哇——非常感谢。我会仔细审查。我同意配色方案的评论,我没有足够关注。
  • 我发现在 Python 2.7 或 3.5 中注释掉脚本中 rowconfigure 和 columnconfigure 类型的所有四个神秘命令对结果没有影响(对窗口的外观和它的帧限制)。
  • @MikeO'Connor:您会在手动调整窗口大小时立即注意到差异。如果没有 rowconfigure 和 columnconfigure 命令,窗口将无法正确调整大小。
  • 啊哈!感谢您回信。中心框架的初始指定高度为 40 让我感到困惑,但关闭 rowconfigure 和 columnconfigure 的显示器不知何故会产生更高高度的中心框架......而顶部和底部框架似乎有他们指定的高度。但现在我看到是分配的 ctr 框架高度有效地设置了中心框架的初始高度。
  • @Bryan Oakley:很好的答案和 tkinter 项目的好模板!
【解决方案2】:

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

使用

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

【讨论】:

    猜你喜欢
    • 2020-10-18
    • 1970-01-01
    • 1970-01-01
    • 2012-11-04
    • 1970-01-01
    • 2011-06-14
    • 1970-01-01
    • 2014-05-11
    • 2012-05-31
    相关资源
    最近更新 更多