Tkinter Gui Not In Proper Place
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:
- An instance (of a widget or a container) is created, and associated with its parent.
- 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:
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):
- Totally outframed one (from your question)
- Partially outframed one (from my answer)
- Correct one, all items in frames
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"