What does 'weight' do in tkinter?
In the simplest terms possible, a non-zero weight causes a row or column to grow if there's extra space. The default is a weight of zero, which means the column will not grow if there's extra space.
Consider the following code, which creates a window larger than the widgets that are inside, and for which no columns have weight:
import tkinter as tk
root = tk.Tk()
root.geometry("200x100")
f1 = tk.Frame(root, background="bisque", width=10, height=100)
f2 = tk.Frame(root, background="pink", width=10, height=100)
f1.grid(row=0, column=0, sticky="nsew")
f2.grid(row=0, column=1, sticky="nsew")
root.grid_columnconfigure(0, weight=0)
root.grid_columnconfigure(1, weight=0)
root.mainloop()
This is what the window looks like:
The reason it looks that way is because tkinter has been told not to give any of the columns any extra space, so the extra space goes unused to the right.
Now, change the code so that we give a weight to just one column:
root.grid_columnconfigure(0, weight=1)
When we restart, we now have a window that looks like this:
What happened? Because column zero had a weight of one, tkinter gave the extra space to this column. You could have set the weight to 1, 100, 100000 and you would get the same result. In this case, all of the extra space goes to this one column.
What happens if you give both columns a weight? The extra space is divided between the columns proportional to their weight. For example, let's say you want a navigation area on the left that takes up 1/4 of the screen and the main area should take up 3/4 of the screen (a 1:3 ratio).
Let's change the weights to look like this:
root.grid_columnconfigure(0, weight=1)
root.grid_columnconfigure(1, weight=3)
Since both columns have weight, extra space is given to both columns. For every four pixels of extra space, column 0 will get 1 and column 1 will get the other 3.
What's more, if you interactively resize the window, the proportion is preserved as much as possible. Here's the same window that I manually resized to be much wider:
How does tkinter's grid_columnconfigure / row_columnconfigure work?
So I think my main question is how does tkinter know that the first grid.column_configure should apply to the first f1 = tk.Frame()?
It doesn't know that, because it doesn't apply to f1
. Both calls to columnconfigure
in your code applies to the root window. It knows this because that's the window it is called on (root.grid_columnconfigure...)
)
If you wanted it to apply to f1
, you would call f1.grid_columnconfigure...
.
It affects f1
because you're calling columnconfigure
on column zero and f1
is in column zero.
Tkinter Grid: How to make entry fill the entire row and be responsive to window resizing?
A good rule of thumb is to always give at least one row and one column a weight greater than zero for every widget that uses grid
to manage child widgets.
Another helpful tip is that if a widget has only a single child, it's easier to use pack
rather than grid
since you can make it responsive all in a single line of code.
So, with that I recommend you use pack
rather than grid
for frm_container
in the main block of code so that the container fills the window it is in.
frm_container.pack(fill="both", expand=True)
The same can be done inside of MyCustomWidget
for main_frm
since it's the only widget directly in self
.
self.main_frm.pack(fill="both", expand=True)
If you prefer using grid
inside of MyCustomWidget
then you need to follow that first rule of thumb and give a weight to the row and column that contains the entry widget.
self.main_frm = ttk.Frame(self)
self.main_frm.grid(row=0, column=0, sticky=tk.NSEW)
self.grid_columnconfigure(0, weight=1)
self.grid_rowconfigure(0, weight=1)
Tkinter - Columns of equal weight are NOT equal width
It is not a bug. weight
determines how extra space is allocated. It doesn't make any guarantees about the size of a row or column.
If you want columns to have a uniform width, use the uniform
option and make them all be part of the same uniform group.
window.columnconfigure(0,weight=1, uniform='third')
window.columnconfigure(1,weight=1, uniform='third')
window.columnconfigure(2,weight=1, uniform='third')
Note: there is nothing special about 'third'
-- it can be any string as long as it's the same string for all three columns.
Related Topics
Specifying and Saving a Figure with Exact Size in Pixels
Numpy Where Function Multiple Conditions
Python: Finding Differences Between Elements of a List
Python: Bind an Unbound Method
How to Load and Play a Video in Pygame
How to Make Smooth Movement in Pygame
Can You Monkey Patch Methods on Core Types in Python
How to Extract Multiple JSON Objects from One File
Can Not Click on a Element: Elementclickinterceptedexception in Splinter/Selenium
Python 2.7 Getting User Input and Manipulating as String Without Quotations
When Do I Need to Call Mainloop in a Tkinter Application
How to Remove Relative Shift in Matplotlib Axis
Why Do My Tkinter Widgets Get Stored as None
Why am I Seeing "Typeerror: String Indices Must Be Integers"
Python Nameerror: Name Is Not Defined
What Are "First-Class" Objects
How to Do a Recursive Sub-Folder Search and Return Files in a List