How to Freeze a pane while re-sizing a window that has frames in python using tkinter and pack?
Question: This is my first post on stackoverflow. I am finally posting because I can not
find this anywhere and have been searching for nearly 4 hours, but I am stuck.

Here is my code example:

    
    
    import tkinter as tk
    from tkinter import *
    root = tk.Tk()
    root.geometry("600x100+200+200")
    leftverticalFrame = Frame(root)
    leftverticalFrame.pack(side=LEFT)
    middleverticlFrame = Frame(root)
    middleverticlFrame.pack(expand=TRUE)
    rightverticalFrame = Frame(root)
    rightverticalFrame.pack(side=RIGHT)
    
    right = tk.Label(rightverticalFrame, text="Right Vertical Status Frame", bg="yellow")
    right.pack(side=tk.RIGHT, fill=BOTH)
    
    left = tk.Label(leftverticalFrame, text = "Left Vertical Navigation Frame", bg="orange")
    left.pack(side=tk.LEFT, fill=BOTH)
    
    bottom = tk.Label(middleverticlFrame, text="Middle Vertical Frame", bg="blue")
    bottom.pack(side=tk.BOTTOM, expand=True, fill=tk.BOTH)
    
    root.mainloop()
    

What I am doing is merely trying to layout the frames individually within the
root because the frames will use different managers. The left frame is
functioning exactly as I want it to, as is the middle frame. The problem is
with the frame on the right.

Notice when you re-size the window making it more narrow, the right frame
comes into the "middle frame's territory". Now the strange thing is the middle
frame does not replicate the same behavior when it comes to the boundary of
the left frame. I want the right frame to behave the same as the middle frame.
Essentially I am trying to make the Left and Right fairly static, but the
middle frame more dynamic. Can anyone tell me what I am doing wrong please?


Answer: An important thing to remember about `pack` is that the `side` attribute
doesn't refer to the side of the window, it refers to the _side of the
remaining available space_. The causes the order in which you pack things and
the side that you pack them to be significant, because each time you pack
something you change the location and amount of remaining available space.

In this case, the problem is that you didn't specify the `side` attribute for
the middle frame, so it defaults to `"top"` (as in, "top of the remaining
space", _not_ "top of the window"). Since there's already something on the
left, this puts it at the top of the remaining space on the right. Then, when
you put the next item on the right, it's on the right but below the thing that
is on the top.

There are at least a couple ways to solve this. The first is to pack the left
and right sides first, and then pack the middle. In this case it doesn't
matter which side you put the middle frame:

    
    
    leftverticalFrame.pack(side=LEFT)
    rightverticalFrame.pack(side=RIGHT)
    middleverticlFrame.pack(expand=TRUE, side=TOP)
    

The second solution is to leave them in the original order, but pack the
middle frame on the left or right instead of the top:

    
    
    leftverticalFrame.pack(side=LEFT)
    middleverticlFrame.pack(expand=TRUE, side=LEFT)
    rightverticalFrame.pack(side=RIGHT)
    

These two variations will initially look identical, or perhaps nearly
identical depending on what else might be in the frames or in the window.
However, the behavior is different when you start to make the window too small
to fit all of the frames.

In such a case, tkinter must eventually start reducing the size of a widget.
It does this in the reverse order that they were packed (read: the last one to
be packed is the first one to be shrunk). That means that if you want the left
and right to be fixed as much as possible, you should pack the middle section
last.

* * *

pro tip: it makes your code easier to read and maintain if you group all of
your layout code together. Consider this code:

    
    
    f1 = Frame(...)
    f1.pack(...)
    f2 = Frame(...)
    f2.pack(...)
    

I think you'll find over time that your code is easier to read and maintain if
you write it like this:

    
    
    f1 = Frame(...)
    f2 = Frame(...)
    ...
    f1.pack(...)
    f2.pack(...)
    ...
    

I think it makes the code much easier to visualize, since all of the layout
for a given parent window is in one place rather than sprinkled throughout the
code.

