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 几何管理器可能看起来古怪和任性,但事实并非如此。您必须了解的一件事是您的操作顺序!

所以主要算法是这样的:

  1. 创建了一个(小部件或容器的)实例,并与其父实例相关联。
  2. 实例已打包。

换句话说:想象一下你正在盖房子!在你的例子中,你开始在五金店或任何地方盖房子,所以你的房子不是按照你的计划建造的。

试着想象每一帧都是房子的地板。里面的小部件是家具!所以首先你要用家具规划你的地板,然后按照你想要的顺序打包。

我稍微修改了你的 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 个变体(来自你的问题,来自我的答案和正确的一个):

  1. 完全不符合一个(来自你的问题)

  1. 部分外框(来自我的回答)

  1. 更正一个,框架中的所有项目

正确代码:

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,此框架的任何子项实际上最终都成为根框架的子项。当您调用 packgrid 时,您最终会将它们放在根 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")