2. Tkinter (Under progress)

2.1. pack vs grid

  • ‘pack()’ command automatically fit the items e.g. in the below code, the “Hello World” will be align to center if we increase the size of the window as shown in Fig. 2.1.
# pythongui.py

import tkinter as tk

tk.Label(text="Hello World").pack()
tk.mainloop()
$ python pythongui.py
../_images/tk1.png

Fig. 2.1 Hello World using pack()

  • we can specify the exact location using ‘grid command’ i.e. in the below code the “Hello World” will be displayed at location ‘(0, 0)’ as shown in Fig. 2.2.
# pythongui.py

import tkinter as tk

tk.Label(text="Hello World").grid(row=0, column=0)
tk.mainloop()
../_images/tk2.png

Fig. 2.2 “Hello world” using grid()

Warning

Note that if we have one element at (0,0) and other element at (0, 5) with ‘no elements between them’, the (0, 5) will be placed beside the (0, 0). In the other words, Tkinter does not keep empty spaces as shown in Fig. 2.3.

# pythongui.py

import tkinter as tk

tk.Label(text="Hello World").grid(row=0, column=0)
tk.Label(text="Hello World").grid(row=0, column=5)
tk.mainloop()
../_images/tk3.png

Fig. 2.3 (0, 5) location is beside (0, 0)

2.2. Widgets

2.2.1. Button

  • In the below code, the message will be changed after pressing the button ‘Hi’.
# pythongui.py

import tkinter as tk

# display message on button click
def click_button():
    msg.configure(text="Hi Meher")

# obj of Tkinter
obj = tk.Tk()

# initial message will be changed after pressing the button
msg = tk.Label(text="Press button")
msg.grid(row=0, column=0)

# run click_button on click
btn_hi = tk.Button(text="Hi", command=click_button)
btn_hi.grid(row=1, column=0)

obj.mainloop()

2.2.2. Textbox

  • In the below code, name is read from textbox and the message “Hello + name” is displayed on pressing the button.

Note

The ‘obj’ is used with all the Widgets, which is the correct way of coding.

# pythongui.py

import tkinter as tk

# display message on button click
def click_button():
    txt = "Hi {}".format(name.get())  # read message from textbox
    msg.configure(text=txt)

# obj of Tkinter
obj = tk.Tk()

# initial message will be changed after pressing the button
msg = tk.Label(obj, text="Press button")
msg.grid(row=0, column=0)

# run click_button on click
btn_hi = tk.Button(obj, text="Hi", command=click_button)
btn_hi.grid(row=1, column=0)

# Textbox
name = tk.StringVar() # name is string variable
txtBox = tk.Entry(obj, width=12, textvariable=name)
txtBox.grid(row=1, column=1)

obj.mainloop()
  • In the below code, ‘state’ and ‘focus’ commands are shown. The ‘focus’ command keeps the cursor on the ‘textbox’ whereas state=’disabled’ will disable the button after the first press.
# pythongui.py

import tkinter as tk

# display message on button click
def click_button():
    txt = "Hi {}".format(name.get())  # read message from textbox
    msg.configure(text=txt)
    btn_hi.configure(state="disabled")

# obj of Tkinter
obj = tk.Tk()

# initial message will be changed after pressing the button
msg = tk.Label(obj, text="Press button")
msg.grid(row=0, column=0)

# run click_button on click
btn_hi = tk.Button(obj, text="Hi", command=click_button)
btn_hi.grid(row=1, column=0)

# Textbox
name = tk.StringVar() # name is string variable
txtBox = tk.Entry(obj, width=12, textvariable=name)
txtBox.grid(row=1, column=1)
txtBox.focus()

obj.mainloop()

2.2.3. Combobox

Combobox is available in ‘ttk’.

# pythongui.py

import tkinter as tk
from tkinter import ttk

# display message on button click
def click_button():
    txt = "Hi {}".format(name.get())  # read message from textbox
    msg.configure(text=txt)

# obj of Tkinter
obj = tk.Tk()
obj.resizable(0, 0) # switch off resizable

# initial message will be changed after pressing the button
msg = tk.Label(obj, text="Press button")
msg.grid(row=0, column=0)

# run click_button on click
btn_hi = tk.Button(obj, text="Hi", command=click_button)
btn_hi.grid(row=1, column=0)

# Combobox
name = tk.StringVar() # name is string variable
cmbBox = ttk.Combobox(obj, width=12, textvariable=name)
cmbBox['values'] = ["Meher", "Krishna", "Patel"]
cmbBox.current(1) # choose second element
cmbBox.grid(row=1, column=1)

obj.mainloop()

2.2.4. Checkbox

# pythongui.py

import tkinter as tk
from tkinter import ttk

# obj of Tkinter
obj = tk.Tk()
obj.resizable(0, 0) # switch off resizable

# display message on button click
def click_button():
    lang_known = []
    if check1Var.get() == 1:
        lang_known.append("C++") # if selected then add to lang_known
    if check2Var.get() == 1:
        lang_known.append("Python")
    txt = "You know {0}".format(lang_known) #print as list
    msg.configure(text=txt)

check1Var = tk.IntVar()
check1 = tk.Checkbutton(obj, text="C++", variable=check1Var)
check1.deselect()  # do not check it
check1.grid(row=0, column=0)

check2Var = tk.IntVar()
check2 = tk.Checkbutton(obj, text="Python", variable=check2Var)
check2.select() # check this box
check2.grid(row=0, column=1)

# initial message will be changed after pressing the button
msg = tk.Label(obj, text="Press button")
msg.grid(row=2, column=0)

# run click_button on click
btn_hi = tk.Button(obj, text="Hi", command=click_button)
btn_hi.grid(row=1, column=0)

obj.mainloop()

2.2.5. Radio button

# pythongui.py

import tkinter as tk
from tkinter import ttk

# obj of Tkinter
obj = tk.Tk()
obj.resizable(0, 0) # switch off resizable

# display message on button click
def click_button():
    lang_known = []
    if radioVar.get() == 0:
        lang_known.append("C++") # if selected then add to lang_known
    if radioVar.get() == 1:
        lang_known.append("Python")
    txt = "You know {0}".format(lang_known) #print as list
    msg.configure(text=txt)

radioVar = tk.IntVar()
radio1 = tk.Radiobutton(obj, text="C++", value=0, variable=radioVar)
radio1.deselect()  # do not radio it
radio1.grid(row=0, column=0)

radio2 = tk.Radiobutton(obj, text="Python", value=1, variable=radioVar)
radio2.select() # radio this box
radio2.grid(row=0, column=1)

# initial message will be changed after pressing the button
msg = tk.Label(obj, text="Press button")
msg.grid(row=2, column=0)

# run click_button on click
btn_submit = tk.Button(obj, text="Submit", command=click_button)
btn_submit.grid(row=1, column=0)

obj.mainloop()

2.2.6. Scrolled text

# pythongui.py

import tkinter as tk
from tkinter import ttk
from tkinter import scrolledtext

# obj of Tkinter
obj = tk.Tk()
obj.resizable(0, 0) # switch off resizable

# initial message will be changed after pressing the button
msg = tk.Label(obj, text="Write message")
msg.grid(row=0, column=0)

width = 15
height = 3
scr = scrolledtext.ScrolledText(obj, width=width, height=height, wrap=tk.WORD)
scr.grid(row=1, column=0)

obj.mainloop()

2.2.7. Spinbox

# pythongui.py

import tkinter as tk
from tkinter import ttk


# obj of Tkinter
obj = tk.Tk()
obj.geometry("500x200+50+50")
obj.resizable(0, 0) # switch off resizable

# relief : GROOVE, FLAT, SUNKEN, RAISED, RIDGE
spinbox = tk.Spinbox(obj, from_=0, to=5, width=3, bd=5, relief=tk.GROOVE)
spinbox.grid()

obj.mainloop()

2.3. Frame

# pythongui.py

import tkinter as tk
from tkinter import ttk
from tkinter import scrolledtext

# obj of Tkinter
obj = tk.Tk()
obj.resizable(0, 0) # switch off resizable

frame1 = tk.LabelFrame(obj, text="Frame 1")
frame1.grid(row=0, column=0)
tk.Label(frame1, text="Lable1").grid(row=0, column=0)
tk.Label(frame1, text="Lable2").grid(row=0, column=1)
tk.Label(frame1, text="Lable3").grid(row=0, column=2)
tk.Button(frame1, text="Submit").grid(row=0, column=3)

frame2 = tk.LabelFrame(obj, text="Frame 2")
frame2.grid(row=0, column=1)
tk.Label(frame2, text="Lable1").grid(row=1, column=0)
tk.Label(frame2, text="Lable2").grid(row=1, column=1)
tk.Label(frame2, text="Lable3").grid(row=1, column=2)
tk.Button(frame2, text="Submit").grid(row=1, column=3)

frame3 = tk.LabelFrame(obj, text="Frame 3")
frame3.grid(row=1, column=1)
tk.Label(frame3, text="Lable1").grid(row=2, column=0)
tk.Label(frame3, text="Lable2").grid(row=2, column=1)
tk.Label(frame3, text="Lable3").grid(row=2, column=2)
tk.Button(frame3, text="Submit").grid(row=2, column=3)

obj.mainloop()

2.5. Message box

Message box is added for “Exit” and “About” options.

# pythongui.py

import tkinter as tk
from tkinter import ttk
from tkinter import messagebox


def exit_qk():
    ans = tk.messagebox.askyesnocancel("Do you want to quit")
    print(ans) # True/False/None
    if ans:
        obj.quit()
        obj.destroy()
        exit()

def about_box(): # info, warning, error, askyesnocancel
    # tk.messagebox.showinfo("Help-Title", "This is help message")
    # tk.messagebox.showwarning("Help-Title", "This is help message")
    tk.messagebox.showerror("Help-Title", "This is help message")

# obj of Tkinter
obj = tk.Tk()
obj.geometry("500x200+50+50")
obj.resizable(0, 0) # switch off resizable


# create menu bar
menu_bar = tk.Menu(obj)
obj.config(menu=menu_bar)
# add item to menu bar
file_menu = tk.Menu(menu_bar, tearoff=0) # create file menu
# add file-menu to menu bar with label
menu_bar.add_cascade(label="File", menu=file_menu)
# add commands to File menu
file_menu.add_command(label="New") # add new to file menu
file_menu.add_command(label="Open")
file_menu.add_command(label="Save")
file_menu.add_separator()
file_menu.add_command(label="Exit", command=exit_qk)

help_menu = tk.Menu(menu_bar, tearoff=0) # create help menu
# add help-menu to menu bar with label
menu_bar.add_cascade(label="Help", menu=help_menu)
# add commands to File menu
help_menu.add_command(label="Help") # add new to help menu
help_menu.add_separator()
help_menu.add_command(label="Credits") # add new to help menu
help_menu.add_command(label="About", command=about_box)

obj.mainloop()

2.6. Tabs

# pythongui.py

import tkinter as tk
from tkinter import ttk
from tkinter import scrolledtext


def exit_qk():
    obj.quit()
    obj.destroy()
    exit()


# obj of Tkinter
obj = tk.Tk()
obj.geometry("500x200+50+50")
obj.resizable(0, 0) # switch off resizable

tabs = ttk.Notebook(obj) # create tab object
# tab 1
tab1 = tk.Frame(tabs)
tabs.add(tab1, text="Tab 1")
# add item to tab 1
label1 = tk.Label(tab1, text="Hello Tab1")
label1.grid()

# tab 2
tab2 = tk.Frame(tabs)
tabs.add(tab2, text="Tab 2")
# add item to tab 2
label2 = tk.Label(tab2, text="Hello Tab1")
label2.grid()

tabs.grid()

obj.mainloop()

2.7. OOPs

2.7.1. Hello World with OOPs

  • Inherit from ‘Frame’
# tkoops.py

import tkinter as tk

# inherit from tk.Frame
class HomePage(tk.Frame):
    def __init__(self):
        tk.Frame.__init__(self)
        self.grid()
        self.createWidgets() # call user defined createWidgets

    def createWidgets(self):
        # create Label
        self.myLabel = tk.Label(self, text="Hello World! This is Home page")
        # set grid parameters
        self.myLabel.grid(
                row=0, column=0,
                rowspan=3, columnspan=2,
                padx=10, pady=10,
                ipadx=3, ipady=3, # internal pad

                # use this or below
                # sticky="nsew"  # north south east west
                sticky=tk.EW
            )

def main():
    app = HomePage()
    app.master.title("Plot graphs")
    app.mainloop()

if __name__ == '__main__':
    main()
  • Inherit for Tk
# tkoops.py

import tkinter as tk

# inherit from tk.Frame
class HomePage(tk.Tk):
    def __init__(self):
        super().__init__()  # inherit parent class init

        # set size of window
        self.geometry("500x400+10+10") # width, height, left margin, top margin

        # frame
        self.frame = tk.Frame(self) # create frame
        self.frame.master.title("Tkinter") # title of frame
        self.frame.grid(padx=20, pady=20) # add some margin from top and bottom

        self.createWidgets() # call user defined createWidgets

    def createWidgets(self):
        # create Label
        self.myLabel = tk.Label(self.frame, text="Hello World! This is Home page")
        # set grid parameters
        self.myLabel.grid(row=0, column=0)

def main():
    app = HomePage()
    app.mainloop()

if __name__ == '__main__':
    main()

2.7.2. Seperate window setup and HomePage

# tkoops.py

import tkinter as tk

# inherit from tk.Frame
class WindowSetup(tk.Tk):
    def __init__(self):
        super().__init__()  # inherit parent class init
        # set size of window
        self.geometry("500x400+10+10") # width, height, left margin, top margin

class HomePage(WindowSetup):
    def __init__(self, title=" "):
        super().__init__()
        # frame
        self.frame = tk.Frame(self) # create frame
        self.frame.master.title(title) # title of frame
        self.frame.grid(padx=20, pady=20) # add some margin from top and bottom

        self.createWidgets() # call user defined createWidgets

    def createWidgets(self):
        # create Label
        self.myLabel = tk.Label(self.frame, text="Hello World! This is Home page")
        # set grid parameters
        self.myLabel.grid(row=0, column=0)

def main():
    app = HomePage("Home Page")
    app.mainloop()

if __name__ == '__main__':
    main()
  • Modfied with frame created in the Tk
# tkoops.py

import tkinter as tk

# inherit from tk.Frame
class WindowSetup(tk.Tk):
    def __init__(self, title):
        super().__init__()  # inherit parent class init
        # set size of window
        self.geometry("500x400+10+10") # width, height, left margin, top margin

        # frame
        self.frame = tk.Frame(self) # create frame
        self.frame.master.title(title) # title of frame
        self.frame.grid(padx=20, pady=20) # add some margin from top and bottom


class HomePage(WindowSetup):
    def __init__(self, title=" "):
        super().__init__(title)
        self.createWidgets() # function call : createWidgets

    def createWidgets(self):
        # create Label
        self.myLabel = tk.Label(self.frame, text="Hello World! This is Home page")
        # set grid parameters
        self.myLabel.grid(row=0, column=0)

def main():
    app = HomePage("Home Page")
    app.mainloop()

if __name__ == '__main__':
    main()

2.7.3. Matplotlib

# tkoops.py

import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.backends.tkagg as tkagg
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

import numpy as np

import tkinter as tk
from tkinter import ttk # ttk changes the look of widgets

# inherit from tk.Frame
class HomePage(tk.Frame):
    def __init__(self):
        tk.Frame.__init__(self)
        self.grid()
        self.createWidgets() # call user defined createWidgets

    def createWidgets(self):
        # create Label
        self.myLabel = ttk.Label(self, text="Hello World! This is Home page")
        # set grid parameters
        self.myLabel.grid(
                row=0, column=0,
                rowspan=3, columnspan=2,
                padx=10, pady=10,
                ipadx=3, ipady=3, # internal pad

                # use this or below
                # sticky="nsew"  # north south east west
                # sticky=tk.E
            )

        x = np.random.rand(100)
        fig = mpl.figure.Figure(figsize=(5,5))
        sf = fig.add_subplot(111)
        sf.plot(x)
        canvas = FigureCanvasTkAgg(fig, self)
        canvas.get_tk_widget().grid(row=5, column=1)
        canvas.show()

def main():
    app = HomePage()
    app.master.title("Plot graphs")
    app.mainloop()

if __name__ == '__main__':
    main()