This page looks best with JavaScript enabled

Python tkinter gui programming

 ·   ·  ☕ 18 min read

    Creating a window

    import tkinter as tk
    
    window=tk.Tk()
    window.title("Hello World")
    window.mainloop()
    

    Centering a window

    # utility function that centers the program window on our screen
    def center_window(toplevel):
        toplevel.update_idletasks()
        screen_width = toplevel.winfo_screenwidth()
        screen_height = toplevel.winfo_screenheight()
        size = tuple(int(_) for _ in toplevel.geometry().split('+')[0].split('x'))
        x = screen_width/2 - size[0]/2
        y = screen_height/2 - size[1]/2
        toplevel.geometry("+%d+%d" % (x, y))
    

    Adding a widget

    Now that you have a window, you can add a widget. Use the tk.Label class to add some text to a window. Create a Label widget with the text “Hello, Everyone” and assign it to a variable called lbl:

    lbl=Tk.Label(text="Hello, Everyone")
    

    The window you created earlier doesn’t change. You just created a Label widget, but you haven’t added it to the window yet. There are several ways to add widgets to a window. Right now, you can use the Label widget’s .pack() method:

    lbl.pack()
    

    window.mainloop() tells Python to run the Tkinter event loop. This method listens for events, such as button clicks or keypresses, and blocks any code that comes after it from running until the window it’s called on is closed.

    window.mainloop()
    

    Using .bind()

    import tkinter as tk
    
    window = tk.Tk()
    
    def handle_keypress(event):
        """Print the character associated to the key pressed"""
        print(event.char)
    
    # Bind keypress event to handle_keypress()
    window.bind("<Key>", handle_keypress)
    
    window.mainloop()
    

    Methods

    • Destroy window : window.destroy()
    • Binding event: window.bind('<event_name>',event_handler)

    Minimize and Restore

    window.iconify()

    window.wm_state("iconic")

    window.deiconify()

    Set icon

    window.iconbitmap(default='icon.ico')

    Make the window unresizable

    window.resizable(False,False)

    Run a function after window open

    window.after(1000,function)

    To run on a thread instead

    window.after(1000,lambda:threading.Thread(target=function_name).start())

    Widgets

    Label

    The Label widget is used to provide a single-line caption for other widgets. It can also contain images.

    import tkinter as tk
    
    label = tk.Label(
        text="Hello, Tkinter",
        foreground="white",  # Set the text color to white
        background="black"  # Set the background color to black
    )
    
    lable.pack()
    

    Getting and setting label text

    label = Tk.Label(text="Hello")
    
    # Retrieve a Label's text
    text = label["text"]
    
    # Set new text for the label
    label["text"] = "Good bye"
    

    some colors are: red, orange, yellow, blue, green, purple, white

    color can be in hex values too

    label = tk.Label(text="Hello, Tkinter", background="#34A2FE")
    

    we can also use short hand property like:

    label = tk.Label(
        text="Hello, Tkinter",
        fg="white",
        bg="black",
        width=10,
        height=10
    )
    

    Button

    The Button widget is used to display the buttons in your application. These buttons can display text or images that convey the purpose of the buttons. You can attach a function or a method to a button which is called automatically when you click the button.

    Syntax

    w=tk.Button(master,option=value,...)

    Parameters

    • master − This represents the parent window.
    • options − Here is the list of most commonly used options for this widget. These options can be used as key-value pairs separated by commas.

    activebackground: Background color when the button is under the cursor.

    activeforeground: Foreground color when the button is under the cursor.

    bd: Border width in pixels. Default is 2.

    bg: Normal background color.

    command: Function or method to be called when the button is clicked.

    fg: Normal foreground (text) color.

    font: Text font to be used for the button’s label.

    height: Height of the button in text lines (for textual buttons) or pixels (for images).

    highlightcolor: The color of the focus highlight when the widget has focus.

    image: Image to be displayed on the button (instead of text).

    justify: How to show multiple text lines: LEFT to left-justify each line; CENTER to center them; or RIGHT to right-justify.

    padx: Additional padding left and right of the text.

    pady: Additional padding above and below the text.

    relief: Relief specifies the type of the border. Some of the values are SUNKEN, RAISED, GROOVE, and RIDGE.

    state: Set this option to DISABLED to gray out the button and make it unresponsive. Has the value ACTIVE when the mouse is over it. Default is NORMAL.

    underline: Default is -1, meaning that no character of the text on the button will be underlined. If nonnegative, the corresponding text character will be underlined.

    width: Width of the button in letters (if displaying text) or pixels (if displaying an image).

    wraplength: If this value is set to a positive number, the text lines will be wrapped to fit within this length.

    Methods

    • flash(): Flash the button several times.
    • invoke(): Calls the buttons callback.
    import tkinter as tk
    from tkinter import messagebox
    
    window=tk.Tk()
    window.geometry("100x100")
    
    def hello():
        msg=messagebox.showinfo("Title","Message")
    
    btn=tk.Button(window,text="click me",command=hello)
    btn.place(x=50,y=50)
    
    window.mainloop()
    

    Binding event

    def handle_click(event):
        print("The button was clicked!")
    
    button = tk.Button(text="Click me!")
    button.bind("<Button-1>", handle_click)
    

    There are other events for mouse button clicks, including “” for the middle mouse button and “” for the right mouse button.

    ** Change color on hover **

    def on_mouse_enter(w,color):
        def on_enter(e):
            e.widget['background']=color
    
        w.bind('<Enter>',on_enter)
    
    def on_mouse_leave(w,color):
        def on_leave(e):
            e.widget['background'] = color
        w.bind('<Leave>',on_leave)
    

    Now we can use the above utility function to change the color or other behaviour on mouse enter and leave

    Entry

    The Entry widget is used to display a single-line text field for accepting values from a user.

    entry=tk.Entry(width=50,fg="yellow",bg="blue")
    
    val=entry.get()
    
    entry.delete(0,4)
    
    entry.delete(3,tk.END)
    
    entry.insert(0,"Hello")
    

    To make it like password field

    lbl=tk.Label(master=window,show="*")
    

    Methods

    • Retrieving text with .get()
    • Deleting text with .delete()
    • Inserting text with .insert()

    Text

    The Text widget is used to display text in multiple lines.

    Same as Entry but with multiline text input

    window=tk.Tk()
    text_box=tk.Text()
    text_box.pack()
    
    val=text_box.get("1.0",tk.END)
    
    text_box.insert(tk.END, "Put me at the end!")
    

    Listbox

    The Listbox widget is used to provide a list of options to a user.

    # !/usr/bin/python3
    from tkinter import *
    
    import tkinter
    
    top = Tk()
    
    Lb1 = Listbox(top)
    Lb1.insert(1, "Python")
    Lb1.insert(2, "Perl")
    Lb1.insert(3, "C")
    Lb1.insert(4, "PHP")
    Lb1.insert(5, "JSP")
    Lb1.insert(6, "Ruby")
    
    Lb1.pack()
    top.mainloop()
    

    Methods

    • insert()
    • index(i)
    • get(first,last=None)
    • delete()
    • curselection()
    • activate(index)
    • see(index)
    • size(index)
    • xview(): make the listbox horizontally scrollable

    PhotoImage

    from tkinter  import *
    import tkinter.filedialog
    
    root = tkinter.Tk()
    
    img=PhotoImage(file="c:/hello.png")
    l1=Label(root,image=img)
    l1.pack()
    

    Message

    The Message widget is used to display multiline text fields for accepting values from a user.

    Checkbutton

    The Checkbutton widget is used to display a number of options as checkboxes. The user can select multiple options at a time.

    from tkinter import *
    
    import tkinter
    
    top = Tk()
    CheckVar1 = IntVar()
    CheckVar2 = IntVar()
    C1 = Checkbutton(top, text = "Music", variable = CheckVar1, \
                     onvalue = 1, offvalue = 0, height=5, \
                     width = 20, )
    C2 = Checkbutton(top, text = "Video", variable = CheckVar2, \
                     onvalue = 1, offvalue = 0, height=5, \
                     width = 20)
    C1.pack()
    C2.pack()
    top.mainloop()
    

    Methods

    deselect(): Clears (turns off) the checkbutton.

    select(): Sets (turns on) the checkbutton.

    invoke(): You can call this method to get the same actions that would occur if the user clicked on the checkbutton to change its state.

    flash(): Flashes the checkbutton a few times between its active and normal colors, but leaves it the way it started.

    toggle(): Clears the checkbutton if set, sets it if cleared.

    Radiobutton

    The Radiobutton widget is used to display a number of options as radio buttons. The user can select only one option at a time.

    from tkinter import *
    
    def sel():
       selection = "You selected the option " + str(var.get())
       label.config(text = selection)
    
    root = Tk()
    var = IntVar()
    R1 = Radiobutton(root, text = "Option 1", variable = var, value = 1,
                      command = sel)
    R1.pack( anchor = W )
    
    R2 = Radiobutton(root, text = "Option 2", variable = var, value = 2,
                      command = sel)
    R2.pack( anchor = W )
    
    R3 = Radiobutton(root, text = "Option 3", variable = var, value = 3,
                      command = sel)
    R3.pack( anchor = W)
    
    label = Label(root)
    label.pack()
    root.mainloop()
    

    Methods

    deselect(): Clears (turns off) the radiobutton.

    select(): Sets (turns on) the radiobutton.

    Spinbox

    The Spinbox widget is a variant of the standard Tkinter Entry widget, which can be used to select from a fixed number of values.

    from tkinter import *
    
    master = Tk()
    
    w = Spinbox(master, from_ = 0, to = 10)
    w.pack()
    
    mainloop()
    

    Methods

    • get(startindex [,endindex]): This method returns a specific character or a range of text.
    • delete(startindex [,endindex]):This method deletes a specific character or a range of text.
    • index(index): Returns the absolute value of an index based on the given index.
    • insert(index [,string]...):This method inserts strings at the specified index location.

    Color Choser

    import tkinter  
    import tkinter.colorchooser
    
    root = tkinter.Tk()
    
    def color_button():  
        color = tkinter.colorchooser.askcolor(parent=root)
        print(color)
        b1.configure(bg=color[1])
    
    b1 = tkinter.Button(root, text='Select Color', command=color_button)  
    b1.pack(fill='x')
    
    root.mainloop()
    

    The Menubutton widget is used to display menus in your application.

    from tkinter import *
    import tkinter
    
    top = Tk()
    
    mb =  Menubutton ( top, text = "condiments", relief = RAISED )
    mb.grid()
    mb.menu  =  Menu ( mb, tearoff = 0 )
    mb["menu"]  =  mb.menu
    
    mayoVar  = IntVar()
    ketchVar = IntVar()
    
    mb.menu.add_checkbutton ( label = "mayo",
                              variable = mayoVar )
    mb.menu.add_checkbutton ( label = "ketchup",
                              variable = ketchVar )
    
    mb.pack()
    top.mainloop()
    

    The Menu widget is used to provide various commands to a user. These commands are contained inside Menubutton.

    from tkinter import *
    def donothing():
       filewin = Toplevel(root)
       button = Button(filewin, text="Do nothing button")
       button.pack()
    
    root = Tk()
    menubar = Menu(root)
    filemenu = Menu(menubar, tearoff = 0)
    filemenu.add_command(label="New", command = donothing)
    filemenu.add_command(label = "Open", command = donothing)
    filemenu.add_command(label = "Save", command = donothing)
    filemenu.add_command(label = "Save as...", command = donothing)
    filemenu.add_command(label = "Close", command = donothing)
    
    filemenu.add_separator()
    
    filemenu.add_command(label = "Exit", command = root.quit)
    menubar.add_cascade(label = "File", menu = filemenu)
    editmenu = Menu(menubar, tearoff=0)
    editmenu.add_command(label = "Undo", command = donothing)
    
    editmenu.add_separator()
    
    editmenu.add_command(label = "Cut", command = donothing)
    editmenu.add_command(label = "Copy", command = donothing)
    editmenu.add_command(label = "Paste", command = donothing)
    editmenu.add_command(label = "Delete", command = donothing)
    editmenu.add_command(label = "Select All", command = donothing)
    
    menubar.add_cascade(label = "Edit", menu = editmenu)
    helpmenu = Menu(menubar, tearoff=0)
    helpmenu.add_command(label = "Help Index", command = donothing)
    helpmenu.add_command(label = "About...", command = donothing)
    menubar.add_cascade(label = "Help", menu = helpmenu)
    
    root.config(menu = menubar)
    root.mainloop()
    

    Methods

    These methods are available on Menu objects −

    add_command (options): Adds a menu item to the menu.

    add_radiobutton( options ): Creates a radio button menu item.

    add_checkbutton( options ): Creates a check button menu item.

    add_cascade(options): Creates a new hierarchical menu by associating a given menu to a parent menu

    add_separator(): Adds a separator line to the menu.

    add( type, options ): Adds a specific type of menu item to the menu.

    delete( startindex [, endindex ]): Deletes the menu items ranging from startindex to endindex.

    entryconfig( index, options ): Allows you to modify a menu item, which is identified by the index, and change its options.

    **index(item)**Returns the index number of the given menu item label.

    insert_separator ( index ): Insert a new separator at the position specified by index.
    invoke ( index ):Calls the command callback associated with the choice at position index. If a checkbutton, its state is toggled between set and cleared; if a radiobutton, that choice is set.

    type ( index ): Returns the type of the choice specified by index: either “cascade”, “checkbutton”, “command”, “radiobutton”, “separator”, or “tearoff”.

    MessageBox

    This module is used to display message boxes in your applications.

    messagebox.FunctionName(title, message [, options])

    You could use one of the following functions with dialogue box −

    • showinfo()
    • showwarning()
    • showerror ()
    • askquestion()
    • askokcancel()
    • askyesno ()
    • askretrycancel ()
    from tkinter import *
    
    from tkinter import messagebox
    
    top = Tk()
    top.geometry("100x100")
    def hello():
       messagebox.showinfo("Say Hello", "Hello World")
    
    B1 = Button(top, text = "Say Hello", command = hello)
    B1.place(x = 35,y = 50)
    
    top.mainloop()
    

    A complete example

    import tkinter  
    import tkinter.messagebox
    
    root = tkinter.Tk()
    
    def display_and_print():  
        tkinter.messagebox.showinfo("Info","Just so you know")
        tkinter.messagebox.showwarning("Warning","Better be careful")
        tkinter.messagebox.showerror("Error","Something went wrong")
    
        okcancel = tkinter.messagebox.askokcancel("What do you think?","Should we go ahead?")
        print(okcancel)
    
        yesno = tkinter.messagebox.askyesno("What do you think?","Please decide")
        print(yesno)
    
        retrycancel = tkinter.messagebox.askretrycancel("What do you think?","Should we try again?")
        print(retrycancel)
    
        answer = tkinter.messagebox.askquestion("What do you think?","What's your answer?")
        print(answer)
    
    b1 = tkinter.Button(root, text='Display dialogs', command=display_and_print)  
    b1.pack(fill='x')
    
    top.mainloop()
    

    Frame

    The Frame widget is used as a container widget to organize other widgets.

    import tkinter as tk
    
    window = tk.Tk()
    frame = tk.Frame()
    
    #adding label ot frame
    label = tk.Label(master=frame)
    label.pack()
    
    frame.pack()
    
    window.mainloop()
    

    Frame border effects

    import tkinter as tk
    
    border_effects = {
        "flat": tk.FLAT,
        "sunken": tk.SUNKEN,
        "raised": tk.RAISED,
        "groove": tk.GROOVE,
        "ridge": tk.RIDGE,
    
    }
    
    window = tk.Tk()
    
    for relief_name, relief in border_effects.items():
        frame = tk.Frame(master=window, relief=relief, borderwidth=5)
        frame.pack(side=tk.LEFT)
    
        label = tk.Label(master=frame, text=relief_name)
    
        label.pack()
    
    window.mainloop()
    

    LabelFrame

    A labelframe is a simple container widget. Its primary purpose is to act as a spacer or container for complex window layouts.

    # !/usr/bin/python3
    from tkinter import *
    
    root = Tk()
    
    labelframe = LabelFrame(root, text = "This is a LabelFrame")
    labelframe.pack(fill = "both", expand = "yes")
     
    left = Label(labelframe, text = "Inside the LabelFrame")
    left.pack()
     
    root.mainloop()
    

    Scale

    The Scale widget is used to provide a slider widget.

    # !/usr/bin/python3
    from tkinter import *
    
    def sel():
       selection = "Value = " + str(var.get())
       label.config(text = selection)
    
    root = Tk()
    var = DoubleVar()
    scale = Scale( root, variable = var )
    scale.pack(anchor = CENTER)
    
    button = Button(root, text = "Get Scale Value", command = sel)
    button.pack(anchor = CENTER)
    
    label = Label(root)
    label.pack()
    
    root.mainloop()
    

    Methods

    get(): This method returns the current value of the scale.

    set ( value ): Sets the scale’s value.

    Scrollbar

    The Scrollbar widget is used to add scrolling capability to various widgets, such as list boxes.

    from tkinter import *
    
    root = Tk()
    scrollbar = Scrollbar(root)
    scrollbar.pack( side = RIGHT, fill = Y )
    
    mylist = Listbox(root, yscrollcommand = scrollbar.set )
    for line in range(100):
       mylist.insert(END, "This is line number " + str(line))
    
    mylist.pack( side = LEFT, fill = BOTH )
    scrollbar.config( command = mylist.yview )
    
    root.mainloop()
    

    Progressbar

    In determinate mode

    from tkinter import * 
    from tkinter.ttk import *
    
    root = Tk() 
    progress = Progressbar(root, orient = HORIZONTAL, 
                  length = 100, mode = 'determinate') 
      
    def bar(): 
        import time 
        progress['value'] = 20
        root.update_idletasks() 
        time.sleep(1) 
      
        progress['value'] = 40
        root.update_idletasks() 
        time.sleep(1) 
      
        progress['value'] = 50
        root.update_idletasks() 
        time.sleep(1) 
      
        progress['value'] = 60
        root.update_idletasks() 
        time.sleep(1) 
      
        progress['value'] = 80
        root.update_idletasks() 
        time.sleep(1) 
        progress['value'] = 100
      
    progress.pack(pady = 10) 
    Button(root, text = 'Start', command = bar).pack(pady = 10) 
    mainloop() 
    

    In indeterminate mode

    from tkinter import * 
    from tkinter.ttk import *
    
    root = Tk() 
    progress = Progressbar(root, orient = HORIZONTAL, 
                length = 100, mode = 'indeterminate') 
    def bar(): 
        import time 
        progress['value'] = 20
        root.update_idletasks() 
        time.sleep(0.5) 
      
        progress['value'] = 40
        root.update_idletasks() 
        time.sleep(0.5) 
      
        progress['value'] = 50
        root.update_idletasks() 
        time.sleep(0.5) 
      
        progress['value'] = 60
        root.update_idletasks() 
        time.sleep(0.5) 
      
        progress['value'] = 80
        root.update_idletasks() 
        time.sleep(0.5) 
      
        progress['value'] = 100
        root.update_idletasks() 
        time.sleep(0.5) 
      
        progress['value'] = 80
        root.update_idletasks() 
        time.sleep(0.5) 
      
        progress['value'] = 60
        root.update_idletasks() 
        time.sleep(0.5) 
      
        progress['value'] = 50
        root.update_idletasks() 
        time.sleep(0.5) 
      
        progress['value'] = 40
        root.update_idletasks() 
        time.sleep(0.5) 
      
        progress['value'] = 20
        root.update_idletasks() 
        time.sleep(0.5) 
        progress['value'] = 0
          
      
    progress.pack(pady = 10) 
    Button(root, text = 'Start', command = bar).pack(pady = 10) 
    mainloop() 
    
    

    Styling the progressbar

    style = ttk.Style()
    style.theme_use('default')
    style.configure("grey.Horizontal.TProgressbar", background='blue')
    bar = Progressbar(window, length=180, style='grey.Horizontal.TProgressbar')
    

    Toplevel

    The Toplevel widget is used to provide a separate window container.

    from tkinter import *
    
    root = Tk()
    root.title("hello")
    top = Toplevel()
    top.title("Python")
    top.mainloop()
    

    PanedWindow

    A PanedWindow is a container widget that may contain any number of panes, arranged horizontally or vertically.

    Canvas

    The Canvas widget is used to draw shapes, such as lines, ovals, polygons and rectangles, in your application.

    The Canvas widget can support the following standard items −

    arc . Creates an arc item, which can be a chord, a pieslice or a simple arc.

    coord = 10, 50, 240, 210 arc = canvas.create_arc(coord, start = 0, extent = 150, fill = “blue”)

    image . Creates an image item, which can be an instance of either the BitmapImage or the PhotoImage classes.

    filename = PhotoImage(file = “sunshine.gif”) image = canvas.create_image(50, 50, anchor = NE, image = filename)

    line . Creates a line item.

    line = canvas.create_line(x0, y0, x1, y1, …, xn, yn, options)

    oval . Creates a circle or an ellipse at the given coordinates. It takes two pairs of coordinates; the top left and bottom right corners of the bounding rectangle for the oval.

    oval = canvas.create_oval(x0, y0, x1, y1, options)

    polygon . Creates a polygon item that must have at least three vertices.

    oval = canvas.create_polygon(x0, y0, x1, y1,…xn, yn, options)

    from tkinter import *
    
    from tkinter import messagebox
    
    top = Tk()
    
    C = Canvas(top, bg = "blue", height = 250, width = 300)
    
    coord = 10, 50, 240, 210
    arc = C.create_arc(coord, start = 0, extent = 150, fill = "red")
    line = C.create_line(10,10,200,200,fill = 'white')
    C.pack()
    top.mainloop()
    

    filedialog

    ** Open and save file dialog**

    import tkinter as tk
    
    from tkinter.filedialog import askopenfilename,asksaveasfilename
    
    from tkinter import *
    from tkinter.ttk import *
    
    def open_file():
        """Open a file for editing."""
        filepath = askopenfilename(
            filetypes=[("Text Files", "*.txt"), ("All Files", "*.*")]
        )
        if not filepath:
            return
        txt_edit.delete("1.0", tk.END)
        with open(filepath, "r",encoding="utf8") as input_file:
            text = input_file.read()
            txt_edit.insert(tk.END, text)
        window.title(f"Simple Text Editor - {filepath}")
    
    
    def save_file():
    
        """Save the current file as a new file."""
    
        filepath = asksaveasfilename(
    
            defaultextension="txt",
    
            filetypes=[("Text Files", "*.txt"), ("All Files", "*.*")],
    
        )
    
        if not filepath:
    
            return
    
        with open(filepath, "w",encoding="utf8") as output_file:
    
            text = txt_edit.get("1.0", tk.END)
    
            output_file.write(text)
    
        window.title(f"Simple Text Editor - {filepath}")
    
    
    
    window=tk.Tk()
    window.title("Filedialog demo")
    window.rowconfigure(0, minsize=400, weight=1)
    window.columnconfigure(1, minsize=400, weight=1)
    
    
    txt_edit = tk.Text(window)
    
    fr_buttons = tk.Frame(window, relief=tk.RAISED, bd=2)
    btn_open = Button(fr_buttons, text="Open", command=open_file)
    btn_save = tk.Button(fr_buttons, text="Save As...",command=save_file)
    
    btn_open.grid(row=0, column=0, sticky="ew", padx=5, pady=5)
    btn_save.grid(row=1, column=0, sticky="ew", padx=5)
    
    fr_buttons.grid(row=0, column=0, sticky="ns")
    txt_edit.grid(row=0, column=1, sticky="nsew")
    
    
    window.mainloop()
    

    ** Select a directory dialog**

    
    from tkinter import filedialog
    
    folder_selected=filedialog.askdirectory()
    
    if file_selected:
        #.. Do your stuff
        pass
    
    
    

    Geometry manager

    The .pack() Geometry Manager

    import tkinter as tk
    
    window = tk.Tk()
    
    frame1 = tk.Frame(master=window, width=100, height=100, bg="red")
    frame1.pack()
    
    frame2 = tk.Frame(master=window, width=50, height=50, bg="yellow")
    frame2.pack()
    
    frame3 = tk.Frame(master=window, width=25, height=25, bg="blue")
    frame3.pack()
    
    window.mainloop()
    

    .pack() places each Frame below the previous one by default, in the order that they’re assigned to the window

    Fill parameter

    tk.X
    tk.Y
    tk.BOTH
    
    import tkinter as tk
    
    window = tk.Tk()
    
    frame1 = tk.Frame(master=window, height=100, bg="red")
    frame1.pack(fill=tk.X)
    
    frame2 = tk.Frame(master=window, height=50, bg="yellow")
    frame2.pack(fill=tk.X)
    
    frame3 = tk.Frame(master=window, height=25, bg="blue")
    frame3.pack(fill=tk.X)
    
    window.mainloop()
    

    Side parameter

    The side keyword argument of .pack() specifies on which side of the window the widget should be placed. These are the available options:

    tk.TOP
    tk.BOTTOM
    tk.LEFT
    tk.RIGHT
    
    import tkinter as tk
    
    window = tk.Tk()
    
    frame1 = tk.Frame(master=window, width=200, height=100, bg="red")
    frame1.pack(fill=tk.Y, side=tk.LEFT)
    
    frame2 = tk.Frame(master=window, width=100, bg="yellow")
    frame2.pack(fill=tk.Y, side=tk.LEFT)
    
    frame3 = tk.Frame(master=window, width=50, bg="blue")
    frame3.pack(fill=tk.Y, side=tk.LEFT)
    
    window.mainloop()
    

    To make the layout truly responsive, you can set an initial size for your frames using the width and height attributes. Then, set the fill keyword argument of .pack() to tk.BOTH and set the expand keyword argument to True:

    import tkinter as tk
    
    window = tk.Tk()
    
    frame1 = tk.Frame(master=window, width=200, height=100, bg="red")
    frame1.pack(fill=tk.BOTH, side=tk.LEFT, expand=True)
    
    frame2 = tk.Frame(master=window, width=100, bg="yellow")
    frame2.pack(fill=tk.BOTH, side=tk.LEFT, expand=True)
    
    frame3 = tk.Frame(master=window, width=50, bg="blue")
    frame3.pack(fill=tk.BOTH, side=tk.LEFT, expand=True)
    
    window.mainloop()
    

    The .place() Geometry Manager

    You can use .place() to control the precise location that a widget should occupy in a window or Frame. You must provide two keyword arguments, x and y, which specify the x- and y-coordinates for the top-left corner of the widget. Both x and y are measured in pixels, not text units.

    import tkinter as tk
    
    window = tk.Tk()
    
    frame = tk.Frame(master=window, width=150, height=150)
    
    frame.pack()
    
    label1 = tk.Label(master=frame, text="I'm at (0, 0)", bg="red")
    
    label1.place(x=0, y=0)
    
    label2 = tk.Label(master=frame, text="I'm at (75, 75)", bg="yellow")
    
    label2.place(x=75, y=75)
    
    window.mainloop()
    

    The .grid() Geometry Manager

    The geometry manager you’ll likely use most often is .grid(), which provides all the power of .pack() in a format that’s easier to understand and maintain.

    .grid() works by splitting a window or Frame into rows and columns. You specify the location of a widget by calling .grid() and passing the row and column indices to the row and column keyword arguments, respectively. Both row and column indices start at 0, so a row index of 1 and a column index of 2 tells .grid() to place a widget in the third column of the second row.

    The following script creates a 3 × 3 grid of frames with Label widgets packed into them:

    import tkinter as tk
    
    window = tk.Tk()
    
    for i in range(3):
        for j in range(3):
            frame = tk.Frame(
                master=window,
                relief=tk.RAISED,
                borderwidth=1
            )
            frame.grid(row=i, column=j,padx=5, pady=5)
            label = tk.Label(master=frame, text=f"Row {i}\nColumn {j}")
            label.pack(padx=5, pady=5)
    
    window.mainloop()
    

    To make it responsive

    You can adjust how the rows and columns of the grid grow as the window is resized using .columnconfigure() and .rowconfigure() on the window object. Remember, the grid is attached to window, even though you’re calling .grid() on each Frame widget. Both .columnconfigure() and .rowconfigure() take three essential arguments:

    The index of the grid column or row that you want to configure (or a list of indices to configure multiple rows or columns at the same time)
    A keyword argument called weight that determines how the column or row should respond to window resizing, relative to the other columns and rows
    A keyword argument called minsize that sets the minimum size of the row height or column width in pixels
    

    weight is set to 0 by default, which means that the column or row doesn’t expand as the window resizes. If every column and row is given a weight of 1, then they all grow at the same rate. If one column has a weight of 1 and another a weight of 2, then the second column expands at twice the rate of the first. Adjust the previous script to better handle window resizing:

    import tkinter as tk
    
    window = tk.Tk()
    
    for i in range(3):
        window.columnconfigure(i, weight=1, minsize=75)
        window.rowconfigure(i, weight=1, minsize=50)
    
        for j in range(0, 3):
            frame = tk.Frame(
                master=window,
                relief=tk.RAISED,
                borderwidth=1
            )
            frame.grid(row=i, column=j, padx=5, pady=5)
    
            label = tk.Label(master=frame, text=f"Row {i}\nColumn {j}")
            label.pack(padx=5, pady=5)
    
    window.mainloop()
    

    By default, widgets are centered in their grid cells.

    You can change the location of each label inside of the grid cell using the sticky parameter. sticky accepts a string containing one or more of the following letters:

    "n" or "N" to align to the top-center part of the cell
    "e" or "E" to align to the right-center side of the cell
    "s" or "S" to align to the bottom-center part of the cell
    "w" or "W" to align to the left-center side of the cell
    

    You can combine multiple letters in a single string to position each Label in the corner of its grid cell

    import tkinter as tk
    
    window = tk.Tk()
    window.columnconfigure(0, minsize=250)
    window.rowconfigure([0, 1], minsize=100)
    
    label1 = tk.Label(text="A")
    label1.grid(row=0, column=0, sticky="ne")
    
    label2 = tk.Label(text="B")
    label2.grid(row=1, column=0, sticky="sw")
    
    window.mainloop()
    

    Themed widget

    from tkinter import *
    from tkinter.ttk import *
    
    
    style = ttk.Style()
    style.configure("BW.TLabel", foreground="black", background="white")
    
    l1 = ttk.Label(text="Test", style="BW.TLabel")
    l2 = ttk.Label(text="Test", style="BW.TLabel")
    

    10 small project for beginners

    • Registration and login
    • ToDo app
    • Text editor like Notepad
    • Password manager
    • Quiz app
    • Calculator
    • Contacts app
    • Temperature (Celsius to Farhenheit) converter
    • Image viewer

    Ohidur Rahman Bappy
    WRITTEN BY
    Ohidur Rahman Bappy
    📚Learner 🐍 Developer