Python GUI Projects with Tkinter (with Source Code)

Welcome to our Python GUI Projects with Tkinter Article. Here we have a compilation of 5 Tkinter GUI Projects we made in Python on our CodersLegacy YouTube Channel. For those of you coming from the Channel, you can find the code here available for you to try for yourself.

For those of you seeing this for the first time, you can find the full explanations for the below code on our Channel, where we write it from scratch.

You can go check out our YouTube Channel with this link.


A Login Page

A simple login form that takes a username and password, and verifies whether it is correct using a file of passwords and usernames. For this program to work, you should have a file called Accounts.txt setup in the same directory.

Watch the Video!

Code
from tkinter import *
from tkinter import messagebox

class Window:
    def __init__(self, master):
        self.master = master

        self.Main = Frame(self.master)
        
        self.L1 = Label(self.Main, text = "Welcome to our Login")
        self.L1.grid(row = 0, column = 1, padx = 5, pady = 5, columnspan = 2)
        
        # Username
        self.L2 = Label(self.Main, text = "Username: ")
        self.L2.grid(row = 1, column = 0, padx = 5, pady = 5)

        self.E1 = Entry(self.Main, width = 30)
        self.E1.grid(row = 1, column = 1, padx = 5, pady = 5, columnspan = 3)

        # Password
        self.L3 = Label(self.Main, text = "Password: ")
        self.L3.grid(row = 2, column = 0, padx = 5, pady = 5)

        self.E2 = Entry(self.Main, show = "*", width = 30)
        self.E2.grid(row = 2, column = 1, padx = 5, pady = 5, columnspan = 3)

        # Buttons
        self.B1 = Button(self.Main, text = "Submit", command = self.verify)
        self.B1.grid(row = 3, column = 2, padx = 5, pady = 5, sticky = "e")

        self.B2 = Button(self.Main, text = "Clear", command = self.clear)
        self.B2.grid(row = 3, column = 3, padx = 5, pady = 5)

        self.Main.pack(padx = 5, pady = 5)

    def clear(self):
        self.E1.delete(0, 'end')
        self.E2.delete(0, 'end')

    def verify(self):
        user = self.E1.get()
        password = self.E2.get()

        file = open("Accounts.txt", "r")

        for line in file:
            temp = line.strip("\n").split(",")

            if user == temp[0] and password == temp[1]:
                print("Your Login Credentials have been Verified")
                return 1

        prompt = messagebox.showerror(title = "Error!", message = "Incorrect Login Details")
        return 0


root = Tk()
window = Window(root)
root.mainloop()

Sample Usernames and Passwords:

CodersLegacy,12345
John Hubbard,2020
Random,0000
Sarah,9009

Registration Form

A Registration form that takes input from the user using a variety of widgets placed in a rather interesting layout using the Pack Layout Manager. This data can then be saved to a MySQL database as permanent storage. For this program you need to have a MySQL database installed to use the data storage feature.

Watch the Video!

Code
from tkinter import *
import mysql.connector


class Window():
    def __init__(self, master):
        self.master = master

        self.Main = Frame(self.master)


        # ----- Section 1

        self.section1 = Frame(self.Main)

        self.L1 = Label(self.section1, text = "First Name")
        self.L1.pack(padx = 5, pady = 5, side = LEFT)

        self.E1 = Entry(self.section1)
        self.E1.pack(padx = 5, pady = 5, side = LEFT)

        self.L2 = Label(self.section1, text = "Last Name")
        self.L2.pack(padx = 5, pady = 5, side = LEFT)

        self.E2 = Entry(self.section1)
        self.E2.pack(padx = 5, pady = 5, side = LEFT)
        
        self.section1.pack(padx = 5, pady = 5, expand = True, fill = X)

        # ----- Section 1


        # ----- Section 2

        self.section2 = Frame(self.Main)

        self.L3 = Label(self.section2, text = "Address")
        self.L3.pack(padx = 5, pady = 5, side = LEFT)

        self.E3 = Entry(self.section2, width = 30)
        self.E3.pack(padx = 5, pady = 5, side = LEFT, expand = True, fill = X)

        self.L4 = Label(self.section2, text = "Postal Code")
        self.L4.pack(padx = 5, pady = 5, side = LEFT)

        self.E4 = Entry(self.section2, width = 6)
        self.E4.pack(padx = 5, pady = 5, side = LEFT)

        
        self.section2.pack(padx = 5, pady = 5, expand = True, fill = X)

        # ----- Section 2



        # ----- Section 3
        self.section3 = Frame(self.Main)
        ## ---- Section 3 sub-frame 1
        
        self.section3_1 = Frame(self.section3)        

        self.L5 = Label(self.section3_1, text = "Pick your Gender")
        self.L5.pack(padx = 5, pady = 5)

        self.Rvar1 = IntVar()

        self.R1 = Radiobutton(self.section3_1, text = "Male", variable = self.Rvar1, value = 1)
        self.R1.pack(padx = 5, pady = 5)
        self.R2 = Radiobutton(self.section3_1, text = "Female", variable = self.Rvar1, value = 2)
        self.R2.pack(padx = 5, pady = 5)
        self.R3 = Radiobutton(self.section3_1, text = "Other", variable = self.Rvar1, value = 3)
        self.R3.pack(padx = 5, pady = 5)

        self.section3_1.pack(padx = 50, pady = 5, side = LEFT)

        ## ---- Section 3 sub-frame 1


        ## ---- Section 3 sub-frame 2
        
        self.section3_2 = Frame(self.section3)        

        self.L5 = Label(self.section3_2, text = "Pick an Option")
        self.L5.pack(padx = 5, pady = 5)

        self.Cvar1 = IntVar()
        self.Cvar2 = IntVar()
        self.Cvar3 = IntVar()

        self.C1 = Checkbutton(self.section3_2, text = "Option1", variable = self.Cvar1)
        self.C1.pack(padx = 5, pady = 5)
        self.C2 = Checkbutton(self.section3_2, text = "Option2", variable = self.Cvar2)
        self.C2.pack(padx = 5, pady = 5)
        self.C3 = Checkbutton(self.section3_2, text = "Option3", variable = self.Cvar3)
        self.C3.pack(padx = 5, pady = 5)

        self.section3_2.pack(padx = 50, pady = 5, side = RIGHT)
        
        ## ---- Section 3 sub-frame 2
        

        self.section3.pack(padx = 5, pady = 5, expand = True, fill = X)
        # ----- Section 3


        # ----- Section 4

        self.section4 = Frame(self.Main)

        self.L6 = Label(self.section4, text = "About yourself: ")
        self.L6.pack(padx = 5, pady = 5)

        self.T1 = Text(self.section4, height = 5, width = 30)
        self.T1.pack(padx =5, pady = 5, expand = True, fill = X)

        self.section4.pack(padx = 5, pady = 5, expand = True, fill = X)
        

        # ----- Section 4

        self.B0 = Button(self.Main, text = "Connect", command = self.connect)
        self.B0.pack(padx = 5, pady = 5, side = LEFT)

        self.B1 = Button(self.Main, text = "Create Table", command = self.create_table)
        self.B1.pack(padx = 5, pady = 5, side = LEFT)

        self.B2 = Button(self.Main, text = "Submit", command = self.submit)
        self.B2.pack(padx = 5, pady = 5, side = RIGHT)

        self.Main.pack(padx = 5, pady = 5, expand = True, fill = X)


    def connect(self):
        try:
            self.db = mysql.connector.connect(
                        host = "localhost",
                        user = "root",
                        password = "shadow1963",
                        database = "data")

            self.cursor = self.db.cursor()
            print("Connection Succeeded")
        except:
            print("Connection Failed")


    def create_table(self):
        try:
            self.cursor.execute("""CREATE TABLE regis_data
                                (firstname VARCHAR(30),
                                 lastname VARCHAR(30),
                                 address VARCHAR(100),
                                 postal_code INT,
                                 gender INT,
                                 choice INT,
                                 comments TEXT)""")
        except:
            print("Table already created")


    def submit(self):
        sql = """INSERT INTO regis_data (firstname, lastname, address, postal_code, gender, choice, comments)
                    VALUES (%s, %s, %s, %s, %s, %s, %s)"""
        values = (self.E1.get(), self.E2.get(), self.E3.get(), self.E4.get(), str(self.Rvar1.get()),
                  str(self.Cvar1.get()) + str(self.Cvar2.get()) + str(self.Cvar3.get()), self.T1.get("1.0", "end"))

        self.cursor.execute(sql, values)
        self.db.commit()
        


root = Tk()
root.resizable(False, False)
window = Window(root)
root.mainloop()

Spreadsheet Program

This is a simple spreadsheet which has some basic features you might expect to see in a spreadsheet software. You can also save all the data in the spreadsheet into a file, and load it back into the spreadsheet at a later time.

Watch the Video!

Code
from tkinter import *


class Window:
    def __init__(self, master):
        self.master = master

        self.Main = Frame(self.master)


        # TOP SECTION
        self.top = Frame(self.Main)

        self.title = Label(self.top, text = "Welcome to our SpreadSheet")
        self.title.pack(padx = 5, pady = 5)
    
        self.top.pack(padx = 5, pady = 5)
        # TOP SECTION
        

        # MIDDLE SECTION
        self.middle = Frame(self.Main)

        self.row = 10
        self.col = 12

        self.cells = [[None for i in range(self.col)] for j in range(self.row)]

        for i in range(self.row):
            for j in range(self.col):
                self.cells[i][j] = Entry(self.middle, width = 5)
                self.cells[i][j].grid(row = i, column = j)

        
        self.middle.pack(padx = 5, pady = 5)
        # MIDDLE SECTION


        # BOTTOM SECTION
        self.bottom = Frame(self.Main)

        self.saveButton = Button(self.bottom, text = "Save", command = self.save)
        self.saveButton.pack(padx = 5, pady = 5, side = RIGHT)

        self.loadButton = Button(self.bottom, text = "Load", command = self.load)
        self.loadButton.pack(padx = 5, pady = 5, side = RIGHT)

        self.clearButton = Button(self.bottom, text = "Clear", command = self.clear)
        self.clearButton.pack(padx = 5, pady = 5, side = LEFT)
        
        self.bottom.pack(padx = 5, pady = 5, expand = True, fill = X)
        # BOTTOM SECTION
        
        self.Main.pack(padx = 5, pady = 5, expand = True, fill = X)


    def save(self):
        file = open("data.txt", "w")

        for i in range(self.row):
            for j in range(self.col):
                file.write(self.cells[i][j].get() + ",")
            file.write("\n")

        file.close()

    def load(self):
        file = open("data.txt", "r")

        self.clear()

        for i in range(self.row):
            temp = file.readline()
            temp = temp.split(",")
            for j in range(self.col):
                self.cells[i][j].insert(0, temp[j].strip())
                
    def clear(self):

        for i in range(self.row):
            for j in range(self.col):
                self.cells[i][j].delete(0, 'end')

        
root = Tk()
window = Window(root)
root.mainloop()

Notepad Application

A simple Notepad application with the basic features found in Text Editors as well as the ability to Undo/Redo Actions.

Watch the Video!

Code
from tkinter import *
from collections import deque


class Window:
    def __init__(self, master):
        self.master = master

        self.Main = Frame(self.master)

        self.stack = deque(maxlen = 10)
        self.stackcursor = 0

        self.L1 = Label(self.Main, text = "This is my NotePad")
        self.L1.pack(padx = 5, pady = 5)

        self.T1 = Text(self.Main, width = 80, height = 20)
        self.T1.pack(padx = 5, pady = 5)

        self.menu = Menu(self.Main)
        self.menu.add_command(label = "Print", command = self.print_stack)
        self.menu.add_command(label = "Undo", command = self.undo)
        self.menu.add_command(label = "Redo", command = self.redo)
        self.master.config(menu = self.menu)

        self.B1 = Button(self.Main, text = "Print", width = 8, command = self.display)
        self.B1.pack(padx = 5, pady = 5, side = LEFT)

        self.B2 = Button(self.Main, text = "Clear", width = 8, command = self.clear)
        self.B2.pack(padx = 5, pady = 5, side = LEFT)

        self.B3 = Button(self.Main, text = "Undo", width = 8, command = self.undo)
        self.B3.pack(padx = 5, pady = 5, side = LEFT)

        self.B4 = Button(self.Main, text = "Redo", width = 8, command = self.redo)
        self.B4.pack(padx = 5, pady = 5, side = LEFT)

        self.Main.pack(padx = 5, pady = 5)

    def display(self):
        print(self.T1.get("1.0", "end"))     

    def clear(self):
        self.T1.delete("1.0", "end")

    def stackify(self):
        self.stack.append(self.T1.get("1.0", "end - 1c"))
        if self.stackcursor < 9: self.stackcursor += 1

    def undo(self):
        if self.stackcursor != 0:
            self.clear()
            if self.stackcursor > 0: self.stackcursor -= 1
            self.T1.insert("0.0", self.stack[self.stackcursor])

    def redo(self):
        if len(self.stack) > self.stackcursor + 1:
            self.clear()
            if self.stackcursor < 9: self.stackcursor += 1
            self.T1.insert("0.0", self.stack[self.stackcursor])

    def print_stack(self):
        i = 0
        for stack in self.stack:
            print(str(i) + " " + stack)
            i += 1

                         

root = Tk()
window = Window(root)
root.bind("<Key>", lambda event: window.stackify())
root.mainloop()

Syntax Highlighter + Code Editor

One of the more Complex GUI Projects with made with Python Tkinter. The Syntax Highlighter we made is here is rather crude, but it has many of the features you will find in simple Code Editors today such as Notepad++. It can color certain keywords, strings and important words, while also having automatic indenting to some extent.

Code
from tkinter import *
from collections import deque


class Window:
    def __init__(self, master):
        self.master = master
        self.master.option_add("*Font", "Verdana 12")

        self.Main = Frame(self.master)

        self.stack = deque(maxlen = 10)
        self.stackcursor = 0

        self.L1 = Label(self.Main, text = "This is my Code Editor")
        self.L1.pack(padx = 5, pady = 5)


        #---------

        self.T1 = Text(self.Main, width = 90, height = 25)

        self.T1.tag_configure("orange", foreground = "orange", font = "Verdana 12")
        self.T1.tag_configure("blue", foreground = "blue", font = "Verdana 12")
        self.T1.tag_configure("purple", foreground = "purple", font = "Verdana 12")
        self.T1.tag_configure("green", foreground = "green", font = "Verdana 12")
        self.T1.tag_configure("red", foreground = "red", font = "Verdana 12")

        self.tags = ["orange", "blue", "purple", "green", "red"]

        self.wordlist = [ ["class", "def", "for", "if", "else", "elif", "import", "from", "as", "break", "while"],
                          ["int", "string", "float", "bool", "__init__"],
                          ["pygame", "tkinter", "sys", "os", "mysql"],
                          ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"] ]

        self.T1.bind("<Return>", lambda event: self.indent(event.widget))
        
        self.T1.pack(padx = 5, pady = 5)

        #---------

        self.menu = Menu(self.Main)
        self.menu.add_command(label = "Print", command = self.print_stack)
        self.menu.add_command(label = "Undo", command = self.undo)
        self.menu.add_command(label = "Redo", command = self.redo)

        self.master.config(menu = self.menu)

        self.B1 = Button(self.Main, text = "Print", width = 8, command = self.display)
        self.B1.pack(padx = 5, pady = 5, side = LEFT)

        self.B2 = Button(self.Main, text = "Clear", width = 8, command = self.clear)
        self.B2.pack(padx = 5, pady = 5, side = LEFT)

        self.B3 = Button(self.Main, text = "Undo", width = 8, command = self.undo)
        self.B3.pack(padx = 5, pady = 5, side = LEFT)

        self.B4 = Button(self.Main, text = "Redo", width = 8, command = self.redo)
        self.B4.pack(padx = 5, pady = 5, side = LEFT)

        self.Main.pack(padx = 5, pady = 5)


    def tagHighlight(self):
        start = "1.0"
        end = "end"
        
        for mylist in self.wordlist:
            num = int(self.wordlist.index(mylist))

            for word in mylist:
                self.T1.mark_set("matchStart", start)
                self.T1.mark_set("matchEnd", start)
                self.T1.mark_set("SearchLimit", end)

                mycount = IntVar()
                
                while True:
                    index= self.T1.search(word,"matchEnd","SearchLimit", count=mycount, regexp = False)

                    if index == "": break
                    if mycount.get() == 0: break

                    self.T1.mark_set("matchStart", index)
                    self.T1.mark_set("matchEnd", "%s+%sc" % (index, mycount.get()))

                    preIndex = "%s-%sc" % (index, 1)
                    postIndex = "%s+%sc" % (index, mycount.get())
                    
                    if self.check(index, preIndex, postIndex):
                        self.T1.tag_add(self.tags[num], "matchStart", "matchEnd")
                        

    def check(self, index, pre, post):
        letters = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p",
                   "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]

        if self.T1.get(pre) == self.T1.get(index):
            pre = index
        else:
            if self.T1.get(pre) in letters:
                return 0

        if self.T1.get(post) in letters:
            return 0

        return 1


    def scan(self):
        start = "1.0"
        end = "end"
        mycount = IntVar()

        regex_patterns = [r'".*"', r'#.*']

        for pattern in regex_patterns:
            self.T1.mark_set("start", start)
            self.T1.mark_set("end", end)

            num = int(regex_patterns.index(pattern))

            while True:
                index = self.T1.search(pattern, "start", "end", count=mycount, regexp = True)

                if index == "": break

                if (num == 1):
                    self.T1.tag_add(self.tags[4], index, index + " lineend")
                elif (num == 0):
                    self.T1.tag_add(self.tags[3], index, "%s+%sc" % (index, mycount.get()))

                self.T1.mark_set("start", "%s+%sc" % (index, mycount.get()))


    def indent(self, widget):

        index1 = widget.index("insert")
        index2 = "%s-%sc" % (index1, 1)
        prevIndex = widget.get(index2, index1)

        prevIndentLine = widget.index(index1 + "linestart")
        print("prevIndentLine ",prevIndentLine)
        prevIndent = self.getIndex(prevIndentLine)
        print("prevIndent ", prevIndent)


        if prevIndex == ":":
            widget.insert("insert", "\n" + "     ")
            widget.mark_set("insert", "insert + 1 line + 5char")

            while widget.compare(prevIndent, ">", prevIndentLine):
                widget.insert("insert", "     ")
                widget.mark_set("insert", "insert + 5 chars")
                prevIndentLine += "+5c"
            return "break"
        
        elif prevIndent != prevIndentLine:
            widget.insert("insert", "\n")
            widget.mark_set("insert", "insert + 1 line")

            while widget.compare(prevIndent, ">", prevIndentLine):
                widget.insert("insert", "     ")
                widget.mark_set("insert", "insert + 5 chars")
                prevIndentLine += "+5c"
            return "break"


    def getIndex(self, index):
        while True:
            if self.T1.get(index) == " ":
                index = "%s+%sc" % (index, 1)
            else:
                return self.T1.index(index)
           
                   
    def update(self):
        self.stackify()
        self.tagHighlight()
        self.scan()

    def display(self):
        print(self.T1.get("1.0", "end"))     

    def clear(self):
        self.T1.delete("1.0", "end")

    def stackify(self):
        self.stack.append(self.T1.get("1.0", "end - 1c"))
        if self.stackcursor < 9: self.stackcursor += 1

    def undo(self):
        if self.stackcursor != 0:
            self.clear()
            if self.stackcursor > 0: self.stackcursor -= 1
            self.T1.insert("0.0", self.stack[self.stackcursor])

    def redo(self):
        if len(self.stack) > self.stackcursor + 1:
            self.clear()
            if self.stackcursor < 9: self.stackcursor += 1
            self.T1.insert("0.0", self.stack[self.stackcursor])

    def print_stack(self):
        i = 0
        for stack in self.stack:
            print(str(i) + " " + stack)
            i += 1

                     
root = Tk()
window = Window(root)
root.bind("<Key>", lambda event: window.update())
root.mainloop()


This marks the end of the Python GUI Projects with Tkinter Article. Any suggestions or contributions for CodersLegacy are more than welcome. Questions regarding the tutorial content can be asked in the comments section below.

Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments