Tkinter dynamically resize Widgets within a Paned Window

Viewed 942

I currently have a window with two LabelPanes. Within the rightPane, I have three LabelFrames. When I resize the window, the bottom most LabelFrame gets larger but the top two remain the size i specified when setting their height. What I would like is for all three of them to uniformly grow when the window is resized in the Y axis. Is this possible?

import tkinter as tk
if __name__ == '__main__':
    appHeight=720
    aspectRatio=16/9
    appWidth=int(appHeight*aspectRatio)
    app=tk.Tk()
    app.title("Title")
    app.minsize(width=appWidth,height=appHeight)
    #================================================================================
    # Setup Panes
    #================================================================================
    #Create Left Pane for settings
    leftPane = tk.PanedWindow(bd=4,relief='raised',bg='red')
    leftPane.pack(fill=tk.BOTH,expand=1)
    #Add Settings Frame to Pane
    settingsFrame = tk.LabelFrame(leftPane,text='Signature Filters',padx=5,pady=5,width=int(appWidth/4))
    leftPane.add(settingsFrame)

    #Create Right Pane for charts
    rightPane = tk.PanedWindow(leftPane,orient=tk.VERTICAL,bd=4,relief=tk.SUNKEN,bg='blue')
    leftPane.add(rightPane)
    #Add Depth Frame to Pane
    depthFrame = tk.LabelFrame(rightPane,text='Depth Signature',padx=5,pady=5,height=int(appHeight/3))
    rightPane.add(depthFrame)
    #Add Velocity Frame to Pane
    velocityFrame = tk.LabelFrame(rightPane,text='Velocity Signature',padx=5,pady=5,height=int(appHeight/3))
    rightPane.add(velocityFrame)
    #Add Depth Frame to Pane
    currentFrame = tk.LabelFrame(rightPane,text='Current Signature',padx=5,pady=5,height=int(appHeight/3))
    rightPane.add(currentFrame)

app.mainloop()
2 Answers

You need to define the stretch option to the string "always" when adding each pane.

rightPane.add(depthFrame, stretch="always")
rightPane.add(velocityFrame, stretch="always")
rightPane.add(currentFrame, stretch="always")

stretch accepts the following values:

  • always This pane will always stretch.
  • first Only if this pane is the first pane (left-most or top-most) will it stretch.
  • last Only if this pane is the last pane (right-most or bottom-most) will it stretch. This is the default value.
  • middle Only if this pane is not the first or last pane will it stretch.
  • never This pane will never stretch.

This information came from the paneconfigure section of the canonical tcl/tk documentation.

You will need to set the sash position. I have wrote some code to make all the panes on the right side equal when the right pane size changes.

import tkinter as tk

if __name__ == '__main__':
    appHeight=720
    aspectRatio=16/9
    appWidth=int(appHeight*aspectRatio)
    app=tk.Tk()
    app.title("Title")
    app.minsize(width=appWidth,height=appHeight)
    #================================================================================
    # Setup Panes
    #================================================================================
    #Create Left Pane for settings
    leftPane = tk.PanedWindow(bd=4,relief='raised',bg='red')
    leftPane.pack(fill=tk.BOTH,expand=1)
    #Add Settings Frame to Pane
    settingsFrame = tk.LabelFrame(leftPane, text='Signature Filters',padx=5,pady=5,width=int(appWidth/4))
    leftPane.add(settingsFrame)

    #Create Right Pane for charts
    rightPane = tk.PanedWindow(leftPane, orient=tk.VERTICAL, bd=4, relief=tk.SUNKEN, bg='blue')

    leftPane.add(rightPane)
    #Add Depth Frame to Pane
    depthFrame = tk.LabelFrame(rightPane, text='Depth Signature', padx=5, pady=5, height=int(appHeight/3))
    rightPane.add(depthFrame)
    #Add Velocity Frame to Pane
    velocityFrame = tk.LabelFrame(rightPane, text='Velocity Signature', padx=5, pady=5, height=int(appHeight/3))
    rightPane.add(velocityFrame)
    #Add Depth Frame to Pane
    currentFrame = tk.LabelFrame(rightPane, text='Current Signature', padx=5, pady=5, height=int(appHeight/3))
    rightPane.add(currentFrame)

    def set_sash(_):
        size = rightPane.winfo_height()//3
        for idx in range(len(rightPane.panes())-1):
            rightPane.sash_place(idx, 4, (idx+1)*size)
    rightPane.bind('<Configure>', set_sash)

app.mainloop()
Related