Managing daily tasks efficiently is essential for productivity. In this article, we will build a simple yet functional To-Do application using Python, SQLite for data storage, and Tkinter for the graphical user interface (GUI). This app allows users to add, edit, and delete tasks with a user-friendly interface.

Features of the To-Do App

  • Add new tasks

  • Edit existing tasks

  • Delete tasks

  • Mark tasks as completed

  • Store tasks in an SQLite database

  • Scrollable task list

Required Libraries

Before running the code, ensure you have Python installed along with Tkinter (which comes pre-installed with Python) and SQLite3.

Setting Up the Database

We start by creating an SQLite database to store our tasks. If the database file does not exist, it will be created automatically.

import sqlite3

# Creating database
conn = sqlite3.connect("task.db")
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS task(
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    task TEXT NOT NULL)
""")
conn.commit()

This snippet initializes a database named task.db and ensures the task table exists with an id and a task column.

Creating the Application Window

Now, let's create a GUI window using Tkinter.

import tkinter as tk
from tkinter import ttk, font, messagebox, PhotoImage

# Creating window
window = tk.Tk()
window.title("To-Do App")
window.configure(bg="#F0F0F0")
window.geometry("500x600")

The Tk() function initializes the main window, sets a title, background color, and dimensions.

Adding Task Input Field and Button

To add tasks, we create an entry field and a button.

frame = tk.Frame(window, bg="#F0F0F0")
frame.pack(pady=10)

task_entry = tk.Entry(frame, font=("Garamond", 14), bg="white", fg="grey", width=30)
task_entry.insert(0, "Write your task here")
task_entry.pack(side=tk.LEFT, padx=10)

def add_task():
    task = task_entry.get().strip()
    if task and task != "Write your task here":
        cursor.execute("INSERT INTO task (task) VALUES (?)", (task,))
        conn.commit()
        load_tasks()
        task_entry.delete(0, tk.END)
    else:
        messagebox.showwarning("Invalid Input", "Please enter a valid task.")

add_button = tk.Button(frame, command=add_task, text="Add Task", bg="#4CAF50", fg="white", height=1, width=15, font=("Roboto", 11))
add_button.pack(side=tk.LEFT, pady=10)

The add_task() function inserts a task into the database and updates the UI.

Displaying Tasks

Tasks are displayed in a scrollable list.

task_list_frame = tk.Frame(window, bg="white")
task_list_frame.pack(fill=tk.BOTH, expand=True)

canvas = tk.Canvas(task_list_frame, bg="white")
canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

scrollbar = ttk.Scrollbar(task_list_frame, orient="vertical", command=canvas.yview)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
canvas.configure(yscrollcommand=scrollbar.set)

canvas_inner = tk.Frame(canvas, bg="white")
canvas.create_window((0, 0), window=canvas_inner, anchor="nw")

The canvas widget allows smooth scrolling, ensuring all tasks remain visible in the interface.

Loading and Displaying Tasks

Tasks are dynamically loaded from the database and displayed.

def load_tasks():
    for widget in canvas_inner.winfo_children():
        widget.destroy()
    cursor.execute("SELECT * FROM task")
    tasks = cursor.fetchall()
    for task in tasks:
        add_task_item(task[0], task[1])

def add_task_item(task_id, task_text):
    task_frame = tk.Frame(canvas_inner, bg="white", bd=1, relief=tk.SOLID)
    task_label = tk.Label(task_frame, text=task_text, font=("Garamond", 16), bg="white", width=25, height=2, anchor='w')
    task_label.pack(side=tk.LEFT, fill=tk.X, padx=10, pady=5)
    
    delete_button = tk.Button(task_frame, command=lambda: delete_task(task_id, task_frame), text="Delete", bg="red", fg="white")
    delete_button.pack(side=tk.RIGHT, padx=5)
    
    task_frame.pack(fill=tk.X, padx=5, pady=5)
    canvas_inner.update_idletasks()
    canvas.config(scrollregion=canvas.bbox("all"))

Deleting Tasks

Users can delete tasks by clicking the delete button.

def delete_task(task_id, task_frame):
    cursor.execute("DELETE FROM task WHERE id = ?", (task_id,))
    conn.commit()
    task_frame.destroy()
    canvas_inner.update_idletasks()
    canvas.config(scrollregion=canvas.bbox("all"))

Running the Application

Finally, we load existing tasks and start the Tkinter event loop.

load_tasks()
window.mainloop()
conn.close()

Conclusion

This To-Do app provides a practical way to manage tasks with an interactive GUI and database storage. It is a great beginner project for learning Tkinter and SQLite. You can enhance it further by adding categories, deadlines, or even syncing with an online database.

Try building and modifying this project to suit your needs!