In this post, I am going to share with you the full Python code of a Tkinter GUI application, which is a to-do app. This code is straightforward to understand. The following steps make it easy to understand this code as follows:
- Pie chart to show the percentage of task completion, remaining tasks, and skipped tasks.
- Counting system to count total tasks, remaining tasks, completed tasks, and skipped tasks in a single place.
- Used scroll bar just to make the interface more charming and smooth to use when it comes to a large number of tasks in your app.
Full Code:
import tkinter as tk from tkinter import messagebox from PIL import Image, ImageTk import matplotlib.pyplot as plt from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg # Create the main window newWindow = tk.Tk() newWindow.title("To-Do List by CodeSpeedy") # Set the window size newWindow.geometry("590x800+270+200") # Set the background color newWindow.configure(bg="#0d1525") # Function to resize images def resize_image(image_path, size, background_color=(13, 21, 37)): with Image.open(image_path) as img: bg = Image.new('RGBA', img.size, background_color + (255,)) bg.paste(img, (0, 0), img) img = bg.resize(size, Image.LANCZOS) return ImageTk.PhotoImage(img) # Resize the icons done_icon = resize_image("done_icon.png", (20, 20), background_color=(13, 21, 37)) delete_icon = resize_image("delete_icon.png", (20, 20), background_color=(13, 21, 37)) skip_icon = resize_image("skip_icon.png", (20, 20), background_color=(13, 21, 37)) # Function to mark a task as done def mark_as_done(task_label, done_button): task_label.config(fg="gray", font=("Helvetica", 18, "overstrike")) done_button.config(image=done_icon, state=tk.DISABLED, disabledforeground="green") update_task_count() # Function to skip a task def skip_task(task_label, skip_button): task_label.config(fg="orange") skip_button.config(state=tk.DISABLED) update_task_count() # Function to delete a specific task def delete_task(task_frame): task_frame.destroy() update_serial_numbers() update_task_count() # Function to add a task def add_task(task=None): if not task: task = task_entry.get() if task: task_frame = tk.Frame(task_container, bg="#1d2332", pady=5) task_number = len(task_container.winfo_children()) + 1 task_label = tk.Label(task_frame, text=f"{task_number}. {task}", bg="#1d2332", fg="#ffffff", font=("Helvetica", 18)) task_label.pack(side=tk.LEFT, padx=10) done_button = tk.Button(task_frame, image=done_icon, command=lambda: mark_as_done(task_label, done_button), bg="#add8e6", fg="#1cbd52", font=("Helvetica", 12)) done_button.pack(side=tk.RIGHT, padx=5) skip_button = tk.Button(task_frame, image=skip_icon, command=lambda: skip_task(task_label, skip_button), bg="#ffa500", fg="#e0194b", font=("Helvetica", 12)) skip_button.pack(side=tk.RIGHT, padx=5) delete_button = tk.Button(task_frame, image=delete_icon, command=lambda: delete_task(task_frame), bg="#ff6347", fg="#e0194b", font=("Helvetica", 12)) delete_button.pack(side=tk.RIGHT, padx=5) task_frame.pack(fill=tk.X, pady=5) task_entry.delete(0, tk.END) update_serial_numbers() update_task_count() canvas.update_idletasks() canvas.configure(scrollregion=canvas.bbox("all")) # Function to update the serial numbers of the tasks def update_serial_numbers(): for index, task_frame in enumerate(task_container.winfo_children()): task_label = task_frame.winfo_children()[0] task_text = task_label.cget("text") if ". " in task_text: task_text = task_text.split(". ", 1)[1] task_label.config(text=f"{index + 1}. {task_text}") # Function to delete all tasks def delete_all_tasks(): for widget in task_container.winfo_children(): widget.destroy() update_task_count() # Function to update task count labels def update_task_count(): total_tasks = len(task_container.winfo_children()) done_tasks = sum(1 for task_frame in task_container.winfo_children() if "overstrike" in task_frame.winfo_children()[0].cget("font")) skipped_tasks = sum(1 for task_frame in task_container.winfo_children() if task_frame.winfo_children()[0].cget("fg") == "orange") remaining_tasks = total_tasks - done_tasks - skipped_tasks total_tasks_label.config(text=f"Total Tasks: {total_tasks}") remaining_tasks_label.config(text=f"Remaining Tasks: {remaining_tasks}") done_tasks_label.config(text=f"Completed Tasks: {done_tasks}") skipped_tasks_label.config(text=f"Skipped Tasks: {skipped_tasks}") update_pie_chart(total_tasks, remaining_tasks, done_tasks, skipped_tasks) # Function to update the pie chart def update_pie_chart(total_tasks, remaining_tasks, done_tasks, skipped_tasks): for widget in pie_chart_frame.winfo_children(): widget.destroy() if total_tasks == 0: return labels = ['Completed Tasks', 'Remaining Tasks', 'Skipped Tasks'] sizes = [done_tasks, remaining_tasks, skipped_tasks] colors = ['#4caf50', '#ffeb3b', '#ffa500'] explode = (0.1, 0, 0) # explode the first slice (Completed Tasks) fig, ax = plt.subplots(figsize=(5, 3), dpi=100) fig.patch.set_facecolor('#0d1525') ax.pie(sizes, explode=explode, colors=colors, autopct='%1.1f%%', shadow=True, startangle=140) ax.axis('equal') ax.legend(labels, loc="best") canvas_chart = FigureCanvasTkAgg(fig, master=pie_chart_frame) canvas_chart.draw() canvas_chart.get_tk_widget().pack() plt.close(fig) # Function to save tasks to a file def save_tasks(): with open("tasks.txt", "w") as file: for task_frame in task_container.winfo_children(): task_label = task_frame.winfo_children()[0] task_text = task_label.cget("text").split(". ", 1)[1] task_done = "1" if "overstrike" in task_label.cget("font") else "0" task_skipped = "1" if task_label.cget("fg") == "orange" else "0" file.write(f"{task_text}|{task_done}|{task_skipped}\n") messagebox.showinfo("Save Tasks", "Tasks have been saved successfully.") # Function to load tasks from a file def load_tasks(): try: with open("tasks.txt", "r") as file: for line in file: task_text, task_done, task_skipped = line.strip().split("|") add_task(task_text) task_frame = task_container.winfo_children()[-1] task_label = task_frame.winfo_children()[0] done_button = task_frame.winfo_children()[1] skip_button = task_frame.winfo_children()[2] if task_done == "1": mark_as_done(task_label, done_button) if task_skipped == "1": skip_task(task_label, skip_button) update_task_count() except FileNotFoundError: pass # Create a canvas to allow scrolling canvas = tk.Canvas(newWindow, bg="#0d1525") canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) # Create a scrollbar scrollbar = tk.Scrollbar(newWindow, orient="vertical", command=canvas.yview) scrollbar.pack(side=tk.LEFT, fill="y") # Configure the canvas canvas.configure(yscrollcommand=scrollbar.set) canvas.bind('<Configure>', lambda e: canvas.configure(scrollregion=canvas.bbox("all"))) # Create a frame inside the canvas task_container = tk.Frame(canvas, bg="#0d1525") canvas.create_window((0, 0), window=task_container, anchor="nw") # Create a navigation bar heading nav_frame = tk.Frame(newWindow, bg="#1d2332") nav_frame.pack(fill=tk.X) nav_label = tk.Label(nav_frame, text="To-Do List", bg="#1d2332", fg="red", font=("Helvetica", 24, "bold")) nav_label.pack(pady=10) # Create an entry widget for adding tasks task_entry = tk.Entry(newWindow, width=35, bg="#1d2332", fg="#ffffff", font=("Helvetica", 22)) task_entry.pack(pady=10) # Create a button to add tasks add_task_button = tk.Button(newWindow, text="Add Task", command=add_task, bg="#add8e6", fg="#000000", font=("Helvetica", 12)) add_task_button.pack(pady=5) # Create a button to delete all tasks delete_all_button = tk.Button(newWindow, text="Delete All Tasks", command=delete_all_tasks, bg="#ff6347", fg="#000000", font=("Helvetica", 12)) delete_all_button.pack(pady=5) # Create buttons to save and load tasks save_button = tk.Button(newWindow, text="Save Tasks", command=save_tasks, bg="#4caf50", fg="#000000", font=("Helvetica", 12)) save_button.pack(pady=5) load_button = tk.Button(newWindow, text="Load Tasks", command=load_tasks, bg="#ffc107", fg="#000000", font=("Helvetica", 12)) load_button.pack(pady=5) # Add vertical gap tk.Label(newWindow, text="", bg="#0d1525").pack(pady=10) # Labels to display task counts total_tasks_label = tk.Label(newWindow, text="Total Tasks: 0", bg="#0d1525", fg="#ffffff", font=("Helvetica", 18)) total_tasks_label.pack(pady=2) remaining_tasks_label = tk.Label(newWindow, text="Remaining Tasks: 0", bg="#0d1525", fg="yellow", font=("Helvetica", 18)) remaining_tasks_label.pack(pady=2) done_tasks_label = tk.Label(newWindow, text="Completed Tasks: 0", bg="#0d1525", fg="lime", font=("Helvetica", 18)) done_tasks_label.pack(pady=2) skipped_tasks_label = tk.Label(newWindow, text="Skipped Tasks: 0", bg="#0d1525", fg="orange", font=("Helvetica", 18)) skipped_tasks_label.pack(pady=2) # Frame for the pie chart pie_chart_frame = tk.Frame(newWindow, bg="#0d1525") pie_chart_frame.pack(pady=20) # Run the main loop newWindow.mainloop()
In this code, there are so many features. This code allows you to add tasks, delete all tasks, save tasks, and load tasks, etc. In this post, I will explain to you a few tasks remaining I provide you a link where you can understand them. Let’s start In this code I added the feature name skip task which skips the task that also shows in the Pie chart. I also add a small icon for skip tasks. For better understanding, you can visit https://youtu.be/iqejggSRIOo?list=PLZbendTO9Iui2lmYuyRq1zspDXWl3_3FG.
Output: