Search code examples
pythontkinterwidgettreeviewttk

Expand one widget vertically while locking another with Tkinter/ttk


I have a treeview inside of a frame that sits on top of another frame containing buttons. I would like the top frame to expand when I resize the window but keep the button frame from doing the same.

Code in Python 2.7.5:

    class MyWindow(Tk.Toplevel, object):
      def __init__(self, master=None, other_stuff=None):
        super(MyWindow, self).__init__(master)
        self.other_stuff = other_stuff
        self.master = master
        self.resizable(True, True)
        self.grid_columnconfigure(0, weight=1)
        self.grid_rowconfigure(0, weight=1)

        # Top Frame
        top_frame = ttk.Frame(self)
        top_frame.grid(row=0, column=0, sticky=Tk.NSEW)
        top_frame.grid_columnconfigure(0, weight=1)
        top_frame.grid_rowconfigure(0, weight=1)
        top_frame.grid_rowconfigure(1, weight=1)

        # Treeview
        self.tree = ttk.Treeview(top_frame, columns=('Value'))
        self.tree.grid(row=0, column=0, sticky=Tk.NSEW)
        self.tree.column("Value", width=100, anchor=Tk.CENTER)
        self.tree.heading("#0", text="Name")
        self.tree.heading("Value", text="Value")

        # Button Frame
        button_frame = ttk.Frame(self)
        button_frame.grid(row=1, column=0, sticky=Tk.NSEW)
        button_frame.grid_columnconfigure(0, weight=1)
        button_frame.grid_rowconfigure(0, weight=1)

        # Send Button
        send_button = ttk.Button(button_frame, text="Send", 
        command=self.on_send)
        send_button.grid(row=1, column=0, sticky=Tk.SW)
        send_button.grid_columnconfigure(0, weight=1)

        # Close Button
        close_button = ttk.Button(button_frame, text="Close", 
        command=self.on_close)
        close_button.grid(row=1, column=0, sticky=Tk.SE)
        close_button.grid_columnconfigure(0, weight=1)

I make the instance elsewhere like this:

    window = MyWindow(master=self, other_stuff=self._other_stuff)

What I have tried: Tried locking resizability which only made the buttons disappear. I also tried changing weights around but my current configuration is the only way everything shows up on screen.

What it should always look like no matter how long the height: When it first launches

What I want to prevent: enter image description here

Thanks in advance.


Solution

  • The problem isn't that the button frame is growing, it's that the top frame is growing but isn't using all of it's space. This is because you are giving row 1 of top_frame a weight of 1 but you don't put anything in row 1. Extra space is being allocated to row 1 because of its weight, but row 1 is empty.

    An easy way to visualize this is to change top_frame to a tk (rather than ttk) frame, and temporarily give it a distinctive background color. You will see that when you resize the window, top_frame fills the window as a whole, but that it is partially empty.

    Create top_frame like this:

    top_frame = Tk.Frame(self, background="pink")
    

    ... yields a screen like the following image when you resize the window. Note that the pink top_frame is showing through, and that button_frame remains its preferred size.

    screenshot showing colored empty space

    You can fix this by simply removing this one line of code:

    top_frame.grid_rowconfigure(1, weight=1)