In this video I’ll show you how to save and open our todo lists for our To-Do list app with Tkinter and Python!

We’ll start out by creating a menu at the top of our app that has dropdowns for Saving a File, Opening a File, and Clearing our current list.

Then we’ll build out the functionality using a filedialog widget to allow us to name our files before we save them. We’ll actually save the files as .dat files.

Python Code: todo.py
(Github Code)

from tkinter import *
from tkinter.font import Font
from tkinter import filedialog
import pickle

root = Tk()
root.title('Codemy.com - ToDo List!')
root.iconbitmap('c:/gui/codemy.ico')
root.geometry("500x500")

# Define our Font
my_font = Font(
	family="Brush Script MT",
	size=30,
	weight="bold")

# Creat frame
my_frame = Frame(root)
my_frame.pack(pady=10)

# Create listbox
my_list = Listbox(my_frame,
	font=my_font,
	width=25,
	height=5,
	bg="SystemButtonFace",
	bd=0,
	fg="#464646",
	highlightthickness=0,
	selectbackground="#a6a6a6",
	activestyle="none")

my_list.pack(side=LEFT, fill=BOTH)

# Create dummy list
#stuff = ["Walk The Dog", "Buy Groceries", "Take A Nap", "Learn Tkinter", "Rule The World"]
# Add dummy list to list box
#for item in stuff:
#	my_list.insert(END, item)

# Create scrollbar
my_scrollbar = Scrollbar(my_frame)
my_scrollbar.pack(side=RIGHT, fill=BOTH)

# Add scrollbar
my_list.config(yscrollcommand=my_scrollbar.set)
my_scrollbar.config(command=my_list.yview)

# create entry box to add items to the list
my_entry = Entry(root, font=("Helvetica", 24), width=26)
my_entry.pack(pady=20)

# Create a button frame
button_frame = Frame(root)
button_frame.pack(pady=20)

# FUNCTIONS
def delete_item():
	my_list.delete(ANCHOR)

def add_item():
	my_list.insert(END, my_entry.get())
	my_entry.delete(0, END)

def cross_off_item():
	# Cross off item
	my_list.itemconfig(
		my_list.curselection(),
		fg="#dedede")
	# Get rid of selection bar
	my_list.selection_clear(0, END)

def uncross_item():
	# Cross off item
	my_list.itemconfig(
		my_list.curselection(),
		fg="#464646")
	# Get rid of selection bar
	my_list.selection_clear(0, END)

def delete_crossed():
	count = 0
	while count < my_list.size():
		if my_list.itemcget(count, "fg") == "#dedede":
			my_list.delete(my_list.index(count))
		
		else: 
			count += 1

def save_list():
	file_name = filedialog.asksaveasfilename(
		initialdir="C:/gui/data",
		title="Save File",
		filetypes=(
			("Dat Files", "*.dat"), 
			("All Files", "*.*"))
		)
	if file_name:
		if file_name.endswith(".dat"):
			pass
		else:
			file_name = f'{file_name}.dat'

		# Delete crossed off items before saving
		count = 0
		while count < my_list.size():
			if my_list.itemcget(count, "fg") == "#dedede":
				my_list.delete(my_list.index(count))
			
			else: 
				count += 1

		# grab all the stuff from the list
		stuff = my_list.get(0, END)

		# Open the file
		output_file = open(file_name, 'wb')

		# Actually add the stuff to the file
		pickle.dump(stuff, output_file)


def open_list():
	file_name = filedialog.askopenfilename(
		initialdir="C:/gui/data",
		title="Open File",
		filetypes=(
			("Dat Files", "*.dat"), 
			("All Files", "*.*"))
		)

	if file_name:
		# Delete currently open list
		my_list.delete(0, END)

		# Open the file
		input_file = open(file_name, 'rb')

		# Load the data from the file
		stuff = pickle.load(input_file)

		# Output stuff to the screen
		for item in stuff:
			my_list.insert(END, item)





def delete_list():
	my_list.delete(0, END)

# Create Menu
my_menu = Menu(root)
root.config(menu=my_menu)

# Add items to the menu
file_menu = Menu(my_menu, tearoff=False)
my_menu.add_cascade(label="File", menu=file_menu)
# Add dropdown items
file_menu.add_command(label="Save List", command=save_list)
file_menu.add_command(label="Open List", command=open_list)
file_menu.add_separator()
file_menu.add_command(label="Clear List", command=delete_list)


# Add some buttons
delete_button = Button(button_frame, text="Delete Item", command=delete_item)
add_button = Button(button_frame, text="Add Item", command=add_item)
cross_off_button = Button(button_frame, text="Cross Off Item", command=cross_off_item)
uncross_button = Button(button_frame, text="Uncross Item", command=uncross_item)
delete_crossed_button = Button(button_frame, text="Delete Crossed", command=delete_crossed)

delete_button.grid(row=0, column=0)
add_button.grid(row=0, column=1, padx=20)
cross_off_button.grid(row=0, column=2)
uncross_button.grid(row=0, column=3, padx=20)
delete_crossed_button.grid(row=0, column=4)

root.mainloop()

John Elder

John is the CEO of Codemy.com where he teaches over 100,000 students how to code! He founded one of the Internet's earliest advertising networks and sold it to a publicly company at the height of the first dot com boom. After that he developed the award-winning Submission-Spider search engine submission software that's been used by over 3 million individuals, businesses, and governments in over 42 countries. He's written several Amazon #1 best selling books on coding, and runs a popular Youtube coding channel.

View all posts

Add comment

Your email address will not be published. Required fields are marked *

John Elder

John is the CEO of Codemy.com where he teaches over 100,000 students how to code! He founded one of the Internet's earliest advertising networks and sold it to a publicly company at the height of...