Tkinter GUI 不在适当的位置
Tkinter GUI not in proper place
我正在尝试创建一个 Tkinter GUI,它是一个顶部带有标签的灰色框,然后在该下拉框下方有一个下拉框,左侧有一个标签来描述它,在该下拉框下方有另一个带有标签的下拉框它的左边。相反,我将标签放在正确的位置,但随后两个下拉框和标签彼此重叠,即使它们位于不同的框架中。
from Tkinter import *
import ttk
class review_gui():
def __init__(self):
self.root = Tk()
self.EDM_GUI(1)
self.root.mainloop()
def EDM_GUI(self, column):
self.EDM_frm = Frame(self.root, background = "grey")
self.EDM_frm.pack(side = "top")
EDM_Label_frm = Frame(self.EDM_frm).pack(side = "top")
EDM_DD_frm = Frame(self.EDM_frm).pack(side = "bottom")
EDM_DB_frm = Frame(EDM_DD_frm).pack(side = "top")
EDM_Port_frm = Frame(EDM_DD_frm).pack(side = "bottom")
EDM_lbl = Label(EDM_Label_frm, text="EDM", fg="black").pack()
EDM_DD_label = Label(EDM_DB_frm, text="Select EDM:", fg="black")
EDM_DD_label.pack(side="left")
EDM_Drop_Down = ttk.Combobox(EDM_DB_frm, state="readonly")
EDM_Drop_Down["values"] = ("One", "Two", "Three")
EDM_Drop_Down.pack(side="right")
EDM_P_label = Label(EDM_Port_frm, text="Select Portfolio:", fg="black")
EDM_P_label.pack(side="left")
Port_Drop_Down = ttk.Combobox(EDM_Port_frm, state="readonly")
Port_Drop_Down["values"] = ("One", "Two", "Three")
Port_Drop_Down.pack(side="right")
rg = review_gui()
标准 pack
几何管理器可能看起来古怪和任性,但事实并非如此。您必须了解的一件事是您的操作顺序!
所以主要算法是这样的:
- 创建了一个(小部件或容器的)实例,并与其父实例相关联。
- 实例已打包。
换句话说:想象一下你正在盖房子!在你的例子中,你开始在五金店或任何地方盖房子,所以你的房子不是按照你的计划建造的。
试着想象每一帧都是房子的地板。里面的小部件是家具!所以首先你要用家具规划你的地板,然后按照你想要的顺序打包。
我稍微修改了你的 EDM_GUI
函数,它看起来像你想要的那样工作!请记住避免在一行中声明和打包,因为 pack
returns None
.
示例:
def EDM_GUI(self, column):
self.EDM_frm = Frame(self.root, background="grey")
self.EDM_frm.pack()
EDM_Label_frm = Frame(self.EDM_frm).pack()
EDM_DD_frm = Frame(self.EDM_frm).pack()
EDM_DB_frm = Frame(EDM_DD_frm)
EDM_Port_frm = Frame(EDM_DD_frm)
EDM_lbl = Label(EDM_Label_frm, text="EDM", fg="black").pack()
EDM_DD_label = Label(EDM_DB_frm, text="Select EDM:", fg="black")
EDM_DD_label.pack(side="left")
EDM_Drop_Down = ttk.Combobox(EDM_DB_frm, state="readonly")
EDM_Drop_Down["values"] = ("One", "Two", "Three")
EDM_Drop_Down.pack(side="right")
EDM_DB_frm.pack(side="top")
EDM_P_label = Label(EDM_Port_frm, text="Select Portfolio:", fg="black")
EDM_P_label.pack(side="left")
Port_Drop_Down = ttk.Combobox(EDM_Port_frm, state="readonly")
Port_Drop_Down["values"] = ("One", "Two", "Three")
Port_Drop_Down.pack(side="right")
EDM_Port_frm.pack(side="bottom")
结果:
加法:
关于 pack
经理的保存和逻辑问题:
我不完全知道 pack
管理器是如何在幕后工作的,但是您可以通过为您的框架添加边框来测试是否出现问题!
只需像这样声明您的框架:FrameVar = Frame(parent, relief='raised', borderwidth=10)
。如您所见 - outframed 小部件直接放置在您的 root
window!
所以我测试了 3 个变体(来自你的问题,来自我的答案和正确的一个):
- 完全不符合一个(来自你的问题)
- 部分外框(来自我的回答)
- 更正一个,框架中的所有项目
正确代码:
def EDM_GUI(self, column):
self.EDM_frm = Frame(self.root)
EDM_Label_frm = Frame(self.EDM_frm)
EDM_lbl = Label(EDM_Label_frm, text="EDM", fg="black").pack()
EDM_Label_frm.pack()
EDM_DD_frm = Frame(self.EDM_frm)
EDM_DB_frm = Frame(EDM_DD_frm)
EDM_DD_label = Label(EDM_DB_frm, text="Select EDM:", fg="black")
EDM_DD_label.pack(side="left")
EDM_Drop_Down = ttk.Combobox(EDM_DB_frm, state="readonly")
EDM_Drop_Down["values"] = ("One", "Two", "Three")
EDM_Drop_Down.pack(side="right")
EDM_DB_frm.pack(side="top")
EDM_Port_frm = Frame(EDM_DD_frm)
EDM_P_label = Label(EDM_Port_frm, text="Select Portfolio:", fg="black")
EDM_P_label.pack(side="left")
Port_Drop_Down = ttk.Combobox(EDM_Port_frm, state="readonly")
Port_Drop_Down["values"] = ("One", "Two", "Three")
Port_Drop_Down.pack(side="right")
EDM_Port_frm.pack(side="bottom")
EDM_DD_frm.pack()
self.EDM_frm.pack()
P.S。仅当您喜欢全局命名空间污染时才使用通配符导入。
问题源于您在创建小部件的同时调用了 pack
:
EDM_Label_frm = Frame(self.EDM_frm).pack(side = "top")
在 python 中,当您执行 foo().bar()
时,结果是 bar()
returns。因此,在 Frame(...).pack(...)
的情况下,您会得到 .pack(...)
returns。 pack
总是returnsNone
,所以EDM_Label_frm
设置为None
。
因为 EDM_Label_frm
设置为 None
,此框架的任何子项实际上最终都成为根框架的子项。当您调用 pack
或 grid
时,您最终会将它们放在根 window.
中
因此,您应该将小部件创建与小部件布局分开。我建议您始终这样做,尽管从技术上讲,您只需要在需要将小部件用作其他命令的参数时这样做。
如果您进行了这一更改,UI 看起来会更接近您的预期。我发现最好始终将父级中的布局分组在一起,这样更容易获得布局的整体视图。在许多情况下,我认为将 all 布局组合在一起会产生更易读的代码。
例如:
EDM_Label_frm = Frame(self.EDM_frm)
EDM_DD_frm = Frame(self.EDM_frm)
EDM_DB_frm = Frame(EDM_DD_frm)
EDM_Port_frm = Frame(EDM_DD_frm)
self.EDM_frm.pack(side = "top")
EDM_Label_frm.pack(side = "top")
EDM_DD_frm.pack(side = "bottom")
EDM_DB_frm.pack(side = "top")
EDM_Port_frm.pack(side = "bottom")
我正在尝试创建一个 Tkinter GUI,它是一个顶部带有标签的灰色框,然后在该下拉框下方有一个下拉框,左侧有一个标签来描述它,在该下拉框下方有另一个带有标签的下拉框它的左边。相反,我将标签放在正确的位置,但随后两个下拉框和标签彼此重叠,即使它们位于不同的框架中。
from Tkinter import *
import ttk
class review_gui():
def __init__(self):
self.root = Tk()
self.EDM_GUI(1)
self.root.mainloop()
def EDM_GUI(self, column):
self.EDM_frm = Frame(self.root, background = "grey")
self.EDM_frm.pack(side = "top")
EDM_Label_frm = Frame(self.EDM_frm).pack(side = "top")
EDM_DD_frm = Frame(self.EDM_frm).pack(side = "bottom")
EDM_DB_frm = Frame(EDM_DD_frm).pack(side = "top")
EDM_Port_frm = Frame(EDM_DD_frm).pack(side = "bottom")
EDM_lbl = Label(EDM_Label_frm, text="EDM", fg="black").pack()
EDM_DD_label = Label(EDM_DB_frm, text="Select EDM:", fg="black")
EDM_DD_label.pack(side="left")
EDM_Drop_Down = ttk.Combobox(EDM_DB_frm, state="readonly")
EDM_Drop_Down["values"] = ("One", "Two", "Three")
EDM_Drop_Down.pack(side="right")
EDM_P_label = Label(EDM_Port_frm, text="Select Portfolio:", fg="black")
EDM_P_label.pack(side="left")
Port_Drop_Down = ttk.Combobox(EDM_Port_frm, state="readonly")
Port_Drop_Down["values"] = ("One", "Two", "Three")
Port_Drop_Down.pack(side="right")
rg = review_gui()
标准 pack
几何管理器可能看起来古怪和任性,但事实并非如此。您必须了解的一件事是您的操作顺序!
所以主要算法是这样的:
- 创建了一个(小部件或容器的)实例,并与其父实例相关联。
- 实例已打包。
换句话说:想象一下你正在盖房子!在你的例子中,你开始在五金店或任何地方盖房子,所以你的房子不是按照你的计划建造的。
试着想象每一帧都是房子的地板。里面的小部件是家具!所以首先你要用家具规划你的地板,然后按照你想要的顺序打包。
我稍微修改了你的 EDM_GUI
函数,它看起来像你想要的那样工作!请记住避免在一行中声明和打包,因为 pack
returns None
.
示例:
def EDM_GUI(self, column):
self.EDM_frm = Frame(self.root, background="grey")
self.EDM_frm.pack()
EDM_Label_frm = Frame(self.EDM_frm).pack()
EDM_DD_frm = Frame(self.EDM_frm).pack()
EDM_DB_frm = Frame(EDM_DD_frm)
EDM_Port_frm = Frame(EDM_DD_frm)
EDM_lbl = Label(EDM_Label_frm, text="EDM", fg="black").pack()
EDM_DD_label = Label(EDM_DB_frm, text="Select EDM:", fg="black")
EDM_DD_label.pack(side="left")
EDM_Drop_Down = ttk.Combobox(EDM_DB_frm, state="readonly")
EDM_Drop_Down["values"] = ("One", "Two", "Three")
EDM_Drop_Down.pack(side="right")
EDM_DB_frm.pack(side="top")
EDM_P_label = Label(EDM_Port_frm, text="Select Portfolio:", fg="black")
EDM_P_label.pack(side="left")
Port_Drop_Down = ttk.Combobox(EDM_Port_frm, state="readonly")
Port_Drop_Down["values"] = ("One", "Two", "Three")
Port_Drop_Down.pack(side="right")
EDM_Port_frm.pack(side="bottom")
结果:
加法:
关于 pack
经理的保存和逻辑问题:
我不完全知道 pack
管理器是如何在幕后工作的,但是您可以通过为您的框架添加边框来测试是否出现问题!
只需像这样声明您的框架:FrameVar = Frame(parent, relief='raised', borderwidth=10)
。如您所见 - outframed 小部件直接放置在您的 root
window!
所以我测试了 3 个变体(来自你的问题,来自我的答案和正确的一个):
- 完全不符合一个(来自你的问题)
- 部分外框(来自我的回答)
- 更正一个,框架中的所有项目
正确代码:
def EDM_GUI(self, column):
self.EDM_frm = Frame(self.root)
EDM_Label_frm = Frame(self.EDM_frm)
EDM_lbl = Label(EDM_Label_frm, text="EDM", fg="black").pack()
EDM_Label_frm.pack()
EDM_DD_frm = Frame(self.EDM_frm)
EDM_DB_frm = Frame(EDM_DD_frm)
EDM_DD_label = Label(EDM_DB_frm, text="Select EDM:", fg="black")
EDM_DD_label.pack(side="left")
EDM_Drop_Down = ttk.Combobox(EDM_DB_frm, state="readonly")
EDM_Drop_Down["values"] = ("One", "Two", "Three")
EDM_Drop_Down.pack(side="right")
EDM_DB_frm.pack(side="top")
EDM_Port_frm = Frame(EDM_DD_frm)
EDM_P_label = Label(EDM_Port_frm, text="Select Portfolio:", fg="black")
EDM_P_label.pack(side="left")
Port_Drop_Down = ttk.Combobox(EDM_Port_frm, state="readonly")
Port_Drop_Down["values"] = ("One", "Two", "Three")
Port_Drop_Down.pack(side="right")
EDM_Port_frm.pack(side="bottom")
EDM_DD_frm.pack()
self.EDM_frm.pack()
P.S。仅当您喜欢全局命名空间污染时才使用通配符导入。
问题源于您在创建小部件的同时调用了 pack
:
EDM_Label_frm = Frame(self.EDM_frm).pack(side = "top")
在 python 中,当您执行 foo().bar()
时,结果是 bar()
returns。因此,在 Frame(...).pack(...)
的情况下,您会得到 .pack(...)
returns。 pack
总是returnsNone
,所以EDM_Label_frm
设置为None
。
因为 EDM_Label_frm
设置为 None
,此框架的任何子项实际上最终都成为根框架的子项。当您调用 pack
或 grid
时,您最终会将它们放在根 window.
因此,您应该将小部件创建与小部件布局分开。我建议您始终这样做,尽管从技术上讲,您只需要在需要将小部件用作其他命令的参数时这样做。
如果您进行了这一更改,UI 看起来会更接近您的预期。我发现最好始终将父级中的布局分组在一起,这样更容易获得布局的整体视图。在许多情况下,我认为将 all 布局组合在一起会产生更易读的代码。
例如:
EDM_Label_frm = Frame(self.EDM_frm)
EDM_DD_frm = Frame(self.EDM_frm)
EDM_DB_frm = Frame(EDM_DD_frm)
EDM_Port_frm = Frame(EDM_DD_frm)
self.EDM_frm.pack(side = "top")
EDM_Label_frm.pack(side = "top")
EDM_DD_frm.pack(side = "bottom")
EDM_DB_frm.pack(side = "top")
EDM_Port_frm.pack(side = "bottom")