Skip to content Skip to sidebar Skip to footer

Tkinter Gui Not In Proper Place

I am trying to create a Tkinter GUI a grey box with a label at the top, then below that a drop down box and with a label to its left describing it and below that another drop down

Solution 1:

The problem stems from you calling pack at the same time that you create a widget:

EDM_Label_frm = Frame(self.EDM_frm).pack(side = "top")

In python, when you do foo().bar(), the result is whatever bar() returns. Thus, in the case of Frame(...).pack(...), you get what .pack(...) returns. pack always returns None, so EDM_Label_frm is set to None.

Because EDM_Label_frm is set to None, any children of this frame actually end up as children of the root frame. When you call pack or grid, you end up placing them inside the root window.

For this reason, you should separate widget creation from widget layout. I suggest you always do this, though technically you only need to do this when you need to use the widget as arguments to other commands.

If you make that one change, the UI will look a lot closer to what you expect. I find it best to always group layout within a parent together so it's easier to get an overall view of the layout. In many cases I think it makes for more readable code when you group all layout together.

For example:

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")

Solution 2:

Standart pack geometry manager may seem bizarre and wayward, but it's not true. One thing that you must understand is the sequence of your actions!

So main alghorithm is this:

  1. An instance (of a widget or a container) is created, and associated with its parent.
  2. The instance is packed.

In other words: imagine that you are building a house! In your example, you start building a house right in the hardware store or wherever, so your house is not built according to your plans.

Try to imagine that each frame is the floor of the house. And the widgets inside it are furniture! So first you plan your floors with furniture and then pack it in order you wish.

I modified little bit your EDM_GUI function and it looks like it's working like you desired! Just remember to avoid declaration and packing in one line, because pack returns None.

Example:

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")

Result:

output

Addition: To your question about preserving and logic of pack manager: I don't exactly know how pack manager works under the hood, but you can test, if something going wrong or not by adding borders to your frames! Just declare your frames like that: FrameVar = Frame(parent, relief='raised', borderwidth=10). As you see - outframed widgets placed directly to your root window!

So I tested 3 variants (from your question, from my answer and correct one):

  1. Totally outframed one (from your question)

totallyoutframed

  1. Partially outframed one (from my answer)

partiallyoutframed

  1. Correct one, all items in frames

correctone

Correct code:

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. Use a wildcard import only if you love global namespace pollution.

Post a Comment for "Tkinter Gui Not In Proper Place"