Search code examples
python-2.7tkintergridlayoutmanager

How to expand widgets size in a frame with respect to other frames in Tkinter (Help on:Tkinter grid management)


Using Tkinter i have created 5 frames, each containing

  • frame0 - label,Entry box and a button(Enter)
  • frame1 - label and list box at the left side
  • frame2 - 2 buttons(select & unselect) at the center
  • frame3 - label and listbox at the right side
  • frame4 - 2 buttons(done & clear)

     ----------------------------------------
     |                 frame0               |
     ----------------------------------------
     |            |            |            |
     |  frame1    |   frame2   |  frame3    |
     |            |            |            |
     ----------------------------------------
     |                 frame4               |
     ----------------------------------------
    

This is my code:

from Tkinter import *

def toplevelwin():

    def clear():
        return

    def select():
        return

    def unselect():
        return

    def done():
        return

    def enter():
        return

    window = Toplevel()

    frame0 = Frame(window)
    frame0.grid(row=0, column=0, sticky=W, padx=5, pady=5, columnspan=2)
    frame0.grid_columnconfigure(1,weight=2)
    lblentry = Label(frame0, text="Entery Box:")
    lblentry.grid(row=0, column=0, sticky=W)
    entrybx = Entry(frame0)
    entrybx.grid(row=1,column=0,sticky=N+S+E+W, columnspan=2)
    entrybt = Button(frame0, text=' Enter ', command=enter)
    entrybt.grid(row=1,column=2,sticky=N+W, padx=3)

    frame1 = Frame(window)
    frame1.grid(row=1, column=0, sticky=E+W, padx=5, pady=5)
    lblshow_lst = Label(frame1, text="List Box 1:")
    lblshow_lst.grid(row=0,sticky=W)
    show_lst = Listbox(frame1)
    show_lst.grid(row=1,sticky=W)

    frame2 = Frame(window)
    frame2.grid(row=1, column=1, sticky=W)
    frame2.grid_columnconfigure(1,weight=1)
    selbtn = Button(frame2, text='Select', command=select)
    selbtn.grid(row=0, padx=5, sticky=E+W)
    selbtn.grid_columnconfigure(1,weight=1)
    uselbtn = Button(frame2, text='Unselect', command=unselect)
    uselbtn.grid(row=1, padx=5, sticky=E+W)
    uselbtn.grid_columnconfigure(1,weight=1)

    frame3 = Frame(window)
    frame3.grid(row=1, column=2, sticky=W, padx=5, pady=5)
    lblsel_lst = Label(frame3, text="List Box 2:")
    lblsel_lst.grid(row=0,sticky=W)
    sel_lst = Listbox(frame3)
    sel_lst.grid(row=1, column=0, sticky=W)

    frame4 = Frame(window)
    frame4.grid(row=2, column=0, sticky=E, padx=5, pady=5)
    Button(frame4, text=' Done ', command=done).grid(row=0, column=0, padx=7 ,pady=2)
    Button(frame4, text='Clear', command=clear).grid(row=0,column=1, padx=7,pady=2)
    window.wait_window(window)


root = Tk()
toplevelwin()
root.mainloop()

And this is how my window looks now:

enter image description here

My Question is:

  • How do i expand frame0 uptill frame3. ie, i want the entry box to extend till frame3's end having the button(enter) to its right side as it is.
  • And i want the bottom frame's button(done and clear) to be placed on the right side of the window

Tries:

  • i tried to increase the size of the entry widget, which in turn pushed frame2 and frame3 to the right side.

  • used sticky=N+S+W+E, which pushed it to the center of the window

  • also did tried sticky=W for the bottom frame containing 2 buttons. They moved to the center but not right


Solution

  • When using grid, to make a widget capable of expanding or shrinking, you need to set its sticky parameter and set its grid cell's weight. Each column and each row of a grid has a weight.

    By default all column and row weights are 0, which mean they will shrink to the smallest valid size.

    To make it expand in the east-west direction, increase its column weight with grid_columnconfigure.

    To make it expand in the north-south direction, increase its row weight with grid_rowconfigure.


    So, for frame0,

    • Use columnspan=3 to make frame0 span 3 columns.
    • Use sticky='WE' to make frame0 stick to both the west and east sides of its cell.
    • Use frame0.grid_columnconfigure(0, weight=1) to increase the grid cell's weight to 1.

    For frame4,

    frame4 = Frame(window)
    frame4.grid(row=2, column=0, sticky='E', padx=5, pady=5, columnspan=3)
    

    would work by making frame4 stick to the east side if its cell. Note that without a weight, frame4 shrinks too; it just shrinks while sticking to the east side, so the buttons it contains end up on the right.

    If you want to make frame4 span the entire space from west to east as shown in your diagram, then use

    frame4.grid(row=2, column=0, sticky='WE', padx=5, pady=5, columnspan=3)
    frame4.grid_columnconfigure(0, weight=1)
    Button(frame4, text=' Done ', command=done).grid(
        row=0, column=0, padx=7, pady=2, sticky='E')
    Button(frame4, text='Clear', command=clear).grid(
        row=0, column=1, padx=7, pady=2, sticky='E')
    

    enter image description here

    from Tkinter import *
    
    def toplevelwin():
        def clear(): return
        select = unselect = done = enter = clear
        window = Toplevel()
    
        frame0 = Frame(window)
        frame0.grid(row=0, column=0, sticky='WE', padx=5, pady=5, columnspan=3)
        frame0.grid_columnconfigure(0, weight=1)
        lblentry = Label(frame0, text="Entry Box:")
        lblentry.grid(row=0, column=0, sticky='W')
        entrybx = Entry(frame0)
        entrybx.grid(row=1, column=0, sticky='NSEW', columnspan=2)
        entrybt = Button(frame0, text=' Enter ', command=enter)
        entrybt.grid(row=1, column=2, sticky='NW', padx=3)
    
        frame1 = Frame(window)
        frame1.grid(row=1, column=0, sticky='EW', padx=5, pady=5)
        lblshow_lst = Label(frame1, text="List Box 1:")
        lblshow_lst.grid(row=0, sticky='W')
        show_lst = Listbox(frame1)
        show_lst.grid(row=1, sticky='W')
    
        frame2 = Frame(window)
        frame2.grid(row=1, column=1, sticky='W')
        selbtn = Button(frame2, text='Select', command=select)
        selbtn.grid(row=0, padx=5, sticky='EW')
        uselbtn = Button(frame2, text='Unselect', command=unselect)
        uselbtn.grid(row=1, padx=5, sticky='EW')
    
        frame3 = Frame(window)
        frame3.grid(row=1, column=2, sticky='W', padx=5, pady=5)
        lblsel_lst = Label(frame3, text="List Box 2:")
        lblsel_lst.grid(row=0, sticky='W')
        sel_lst = Listbox(frame3)
        sel_lst.grid(row=1, column=0, sticky='W')
    
        frame4 = Frame(window)
        frame4.grid(row=2, column=0, sticky='WE', padx=5, pady=5, columnspan=3)
        frame4.grid_columnconfigure(0, weight=1)
        Button(frame4, text=' Done ', command=done).grid(
            row=0, column=0, padx=7, pady=2, sticky='E')
        Button(frame4, text='Clear', command=clear).grid(
            row=0, column=1, padx=7, pady=2, sticky='E')
    
        window.wait_window(window)
    
    
    root = Tk()
    toplevelwin()
    root.mainloop()