Managing daily tasks efficiently is crucial for productivity and organization. Whether you're juggling multiple projects or keeping track of personal errands, a well-designed To-Do List application can make a significant difference. This comprehensive Python application offers both Command-Line Interface (CLI) and Graphical User Interface (GUI) versions, catering to diverse user preferences. By leveraging object-oriented programming, error handling, and persistent storage, this app ensures a robust and user-friendly experience.
The CLI version offers a straightforward approach to managing tasks directly from the terminal. Here's the Python code implementing the CLI-based To-Do List application:
import os
import datetime
import json
class ToDoList:
def __init__(self, filename='tasks.json'):
self.filename = filename
self.tasks = self.load_tasks()
def load_tasks(self):
if os.path.exists(self.filename):
with open(self.filename, 'r') as file:
try:
return json.load(file)
except json.JSONDecodeError:
return []
return []
def save_tasks(self):
with open(self.filename, 'w') as file:
json.dump(self.tasks, file, indent=4)
def add_task(self, task):
date = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
self.tasks.append({"task": task, "date": date, "completed": False})
self.save_tasks()
print(f"Task '{task}' added successfully.")
def view_tasks(self):
if not self.tasks:
print("No tasks in the list.")
return
print("\nYour To-Do List:")
for index, task in enumerate(self.tasks, 1):
status = "✓" if task["completed"] else "✗"
print(f"{index}. [{status}] {task['task']} (Added: {task['date']})")
print()
def mark_completed(self, task_number):
if 1 <= task_number <= len(self.tasks):
self.tasks[task_number - 1]["completed"] = True
self.save_tasks()
print(f"Task {task_number} marked as completed.")
else:
print("Invalid task number.")
def delete_task(self, task_number):
if 1 <= task_number <= len(self.tasks):
removed_task = self.tasks.pop(task_number - 1)
self.save_tasks()
print(f"Task '{removed_task['task']}' deleted from the list.")
else:
print("Invalid task number.")
def main():
todo_list = ToDoList()
while True:
print("\n--- To-Do List App ---")
print("1. Add Task")
print("2. View Tasks")
print("3. Mark Task as Completed")
print("4. Delete Task")
print("5. Exit")
choice = input("Enter your choice (1-5): ").strip()
if choice == "1":
task = input("Enter the task: ").strip()
if task:
todo_list.add_task(task)
else:
print("Task cannot be empty.")
elif choice == "2":
todo_list.view_tasks()
elif choice == "3":
try:
task_number = int(input("Enter the task number to mark as completed: ").strip())
todo_list.mark_completed(task_number)
except ValueError:
print("Please enter a valid number.")
elif choice == "4":
try:
task_number = int(input("Enter the task number to delete: ").strip())
todo_list.delete_task(task_number)
except ValueError:
print("Please enter a valid number.")
elif choice == "5":
print("Exiting the To-Do List App. Goodbye!")
break
else:
print("Invalid choice. Please try again.")
if __name__ == "__main__":
main()
The CLI version utilizes object-oriented programming to manage tasks effectively. Here's a breakdown of the key components:
os
and json
for file handling.datetime
for timestamping tasks.__init__:
Initializes the task list by loading existing tasks from a JSON file.load_tasks:
Loads tasks from the specified JSON file if it exists; otherwise, initializes an empty list.save_tasks:
Saves the current task list to the JSON file, ensuring data persistence.add_task:
Adds a new task with a timestamp and saves the updated list.view_tasks:
Displays all tasks with their status and timestamp.mark_completed:
Marks a specific task as completed based on user input.delete_task:
Removes a specific task from the list.The GUI version leverages the Tkinter library to provide a more interactive and visually appealing interface. Here's the Python code implementing the GUI-based To-Do List application:
import tkinter as tk
from tkinter import ttk, messagebox
import datetime
import json
import os
class TodoApp:
def __init__(self, root, filename='tasks.json'):
self.root = root
self.root.title("To-Do List Application")
self.root.geometry("500x600")
self.filename = filename
self.tasks = self.load_tasks()
self.create_widgets()
def load_tasks(self):
if os.path.exists(self.filename):
with open(self.filename, 'r') as file:
try:
return json.load(file)
except json.JSONDecodeError:
return []
return []
def save_tasks(self):
with open(self.filename, 'w') as file:
json.dump(self.tasks, file, indent=4)
def create_widgets(self):
# Frame for adding tasks
add_frame = ttk.Frame(self.root)
add_frame.pack(pady=10)
self.task_entry = ttk.Entry(add_frame, width=40)
self.task_entry.pack(side=tk.LEFT, padx=5)
add_button = ttk.Button(add_frame, text="Add Task", command=self.add_task)
add_button.pack(side=tk.LEFT)
# Listbox to display tasks
self.task_listbox = tk.Listbox(self.root, width=50, height=20)
self.task_listbox.pack(pady=20)
# Frame for action buttons
action_frame = ttk.Frame(self.root)
action_frame.pack(pady=10)
complete_button = ttk.Button(action_frame, text="Mark as Completed", command=self.mark_completed)
complete_button.pack(side=tk.LEFT, padx=5)
delete_button = ttk.Button(action_frame, text="Delete Task", command=self.delete_task)
delete_button.pack(side=tk.LEFT, padx=5)
self.update_listbox()
def add_task(self):
task = self.task_entry.get().strip()
if task:
date = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
self.tasks.append({"task": task, "date": date, "completed": False})
self.save_tasks()
self.update_listbox()
self.task_entry.delete(0, tk.END)
else:
messagebox.showwarning("Input Error", "Please enter a task.")
def update_listbox(self):
self.task_listbox.delete(0, tk.END)
for task in self.tasks:
status = "✓" if task["completed"] else "✗"
self.task_listbox.insert(tk.END, f"[{status}] {task['task']} (Added: {task['date']})")
def mark_completed(self):
selected_indices = self.task_listbox.curselection()
if not selected_indices:
messagebox.showwarning("Selection Error", "Please select a task to mark as completed.")
return
index = selected_indices[0]
self.tasks[index]["completed"] = True
self.save_tasks()
self.update_listbox()
def delete_task(self):
selected_indices = self.task_listbox.curselection()
if not selected_indices:
messagebox.showwarning("Selection Error", "Please select a task to delete.")
return
index = selected_indices[0]
del self.tasks[index]
self.save_tasks()
self.update_listbox()
def main():
root = tk.Tk()
app = TodoApp(root)
root.mainloop()
if __name__ == "__main__":
main()
The GUI version enhances user experience through a graphical interface. Here's a detailed explanation of its components:
tkinter
and related modules for GUI elements.datetime
and json
for task management.os
for file handling.__init__:
Sets up the main window, loads existing tasks, and initializes widgets.load_tasks:
Loads tasks from a JSON file if available.save_tasks:
Saves the current tasks to a JSON file.create_widgets:
Creates and arranges GUI components including entry fields, buttons, and listbox.add_task:
Adds a new task from the input field and updates the listbox.update_listbox:
Refreshes the listbox to reflect the current tasks.mark_completed:
Marks the selected task as completed.delete_task:
Removes the selected task from the list.To ensure the To-Do List application is robust and user-friendly, consider implementing the following enhancements and adhering to best practices:
Using JSON files for storing tasks allows for data persistence. This ensures that tasks are not lost when the application is closed.
Implementing the application using classes not only organizes code better but also makes it easier to expand functionality in the future.
Incorporating try-except blocks and input validations prevents the application from crashing and guides users towards correct usage.
A clear and intuitive interface, whether CLI or GUI, enhances user satisfaction and ease of use. Providing immediate feedback after actions reinforces user control.
Consider adding features such as:
Feature | Command-Line Interface (CLI) | Graphical User Interface (GUI) |
---|---|---|
Setup Complexity | Simple, runs in terminal. | Requires a GUI library like Tkinter. |
User Interaction | Text-based input and output. | Interactive elements like buttons, listboxes. |
Visual Appeal | Basic, limited to text. | Enhanced visual interface. |
Ease of Use | Requires familiarity with command-line operations. | More intuitive for general users. |
Features Extensibility | Easy to add via code commands. | May require more UI design efforts for new features. |
Creating a To-Do List application in Python is an excellent way to hone programming skills while building a practical tool. Whether you prefer a Command-Line Interface or a Graphical User Interface, Python's flexibility allows for the creation of feature-rich applications tailored to user needs. By incorporating object-oriented principles, persistent storage, and robust error handling, this To-Do List app stands as a reliable solution for task management.