I'm (almost) a poor programmer-virgin so please go easy on me.
This is my second attempt at making a program and this is turning out to be a bit more than I can navigate, I am afraid. I ask for your help after a long time of trying to solve this.
I am basically making a ToDo-list but wanted it to have some more functionality than just being a boring list.
How I imagine it in my head is that the user adds a task into an entry widget, which would then be displayed in a Listbox. Each string in the Listbox would then have a value associated with it (which I need to some calculations for the functionality I want the program to have). So what I think I kind of want is every string in the Listbox to be made a variable and then associated with that variable I want a value.
I will try to show you:
Here I am adding the string that I want to become a new variable
Then I specify a number from a drop down menu. I want this number to be the value of the variable/string from previous step.
I really hope one of you can lead me in the right direction in a way that (preferably) doesn't require me to change things up too much. Things are still very slippery to me and it is already fairly hard for me to navigate the code. The purpose is simply that I want to do some calculations with the (hopefully) soon-to-be values associated with each task. Thanks in advance if any of you dare!
The associated code is here:
import tkinter.messagebox # Import the messagebox module
import pickle # Module to save to .dat
import tkinter as tk
root = tk.Tk() #
root.title('SmaToDo') # Name of the program/window
def new_task():
global entry_task
global task_window
task_window = Toplevel(root)
task_window.title('Add a new task')
task_label = tk.Label(task_window, text = 'Title your task concisely:', justify='center')
task_label.pack()
# Entry for tasks in new window
entry_task = tkinter.Entry(task_window, width=50, justify='center')
entry_task.pack()
# Add task button in new window
button_add_task = tkinter.Button(task_window, text='Add task', width=42, command=lambda: [add_task(), impact()])
button_add_task.pack()
def add_task():
global task
global impact_window
task = entry_task.get() # we get the task from entry_task and we get the input from the entry_task type-field with .get()
if task != '': # If textbox inputfield is NOT empty do this:
listbox_tasks.insert(tkinter.END, task)
entry_task.delete(0, tkinter.END) # Slet hvad der står i inputfeltet fra første bogstav til sidste (0, tkinter.END)
task_window.destroy()
else:
tkinter.messagebox.showwarning(title='Whoops', message='You must enter a task')
task_window.destroy()
def delete_task():
try:
task_index = listbox_tasks.curselection()[0]
listbox_tasks.delete(task_index)
except:
tkinter.messagebox.showwarning(title='Oops', message='You must select a task to delete')
def save_tasks():
tasks = listbox_tasks.get(0, listbox_tasks.size())
pickle.dump(tasks, open('tasks.dat', 'wb'))
def prioritize_tasks():
pass
# Create UI
frame_tasks = tkinter.Frame(root)
frame_tasks.pack()
scrollbar_tasks = tkinter.Scrollbar(frame_tasks)
scrollbar_tasks.pack(side=tkinter.RIGHT, fill=tkinter.Y)
listbox_tasks = tkinter.Listbox(frame_tasks, height=10, width=50, justify='center') # tkinter.Listbox(where it should go, height=x, width=xx)
listbox_tasks.pack()
listbox_tasks.config(yscrollcommand=scrollbar_tasks.set)
scrollbar_tasks.config(command=listbox_tasks.yview)
try:
tasks = pickle.load(open('tasks.dat', 'rb'))
listbox_tasks.delete(0, tkinter.END)
for task in tasks:
listbox_tasks.insert(tkinter.END, task)
except:
tkinter.messagebox.showwarning(title='Phew', message='You have no tasks')
# Add task button
button_new_task = tkinter.Button(root, text='New task', width=42, command=new_task)
button_new_task.pack()
button_delete_task = tkinter.Button(root, text='Delete task', width=42, command=delete_task)
button_delete_task.pack()
button_save_tasks = tkinter.Button(root, text='Save tasks', width=42, command=save_tasks)
button_save_tasks.pack()
button_prioritize_tasks = tkinter.Button(root, text='Prioritize', width=42, command=prioritize_tasks)
button_prioritize_tasks.pack()
root.mainloop()
The simple way is to add another list
to store the impact values. You need to synchronize the task list and the impact list.
Below is the modified code:
import pickle # Module to save to .dat
import tkinter as tk
from tkinter import messagebox
import random
TASKS_FILE = "tasks.dat"
task_impacts = [] # store impact of tasks
root = tk.Tk() #
root.title('SmaToDo') # Name of the program/window
def impact():
# assign random impact to new task
task_impacts.append(random.randint(1, 11))
def new_task():
def add_task():
task = entry_task.get().strip()
if task:
listbox_tasks.insert(tk.END, task)
impact() # get the impact of the task
else:
messagebox.showwarning(title='Whoops', message='You must enter a task')
task_window.destroy()
task_window = tk.Toplevel(root)
task_window.title('Add a new task')
task_label = tk.Label(task_window, text = 'Title your task concisely:', justify='center')
task_label.pack()
# Entry for tasks in new window
entry_task = tk.Entry(task_window, width=50, justify='center')
entry_task.pack()
# Add task button in new window
button_add_task = tk.Button(task_window, text='Add task', width=42, command=add_task)
button_add_task.pack()
def delete_task():
try:
task_index = listbox_tasks.curselection()[0]
listbox_tasks.delete(task_index)
task_impacts.pop(task_index) # remove corresponding impact value as well
except:
messagebox.showwarning(title='Oops', message='You must select a task to delete')
def load_tasks():
try:
with open(TASKS_FILE, 'rb') as f:
tasks = pickle.load(f)
listbox_tasks.delete(0, tk.END)
task_impacts.clear()
for task, impact in tasks:
listbox_tasks.insert(tk.END, task)
task_impacts.append(impact)
except:
messagebox.showwarning(title='Phew', message='You have no tasks')
def save_tasks():
tasks = zip(listbox_tasks.get(0, tk.END), task_impacts)
with open(TASKS_FILE, "wb") as f:
pickle.dump(tasks, f)
def prioritize_tasks():
print(list(zip(listbox_tasks.get(0, tk.END), task_impacts)))
# Create UI
frame_tasks = tk.Frame(root)
frame_tasks.pack()
scrollbar_tasks = tk.Scrollbar(frame_tasks)
scrollbar_tasks.pack(side=tk.RIGHT, fill=tk.Y)
listbox_tasks = tk.Listbox(frame_tasks, height=10, width=50, justify='center') # tkinter.Listbox(where it should go, height=x, width=xx)
listbox_tasks.pack()
listbox_tasks.config(yscrollcommand=scrollbar_tasks.set)
scrollbar_tasks.config(command=listbox_tasks.yview)
# Add task button
button_new_task = tk.Button(root, text='New task', width=42, command=new_task)
button_new_task.pack()
button_delete_task = tk.Button(root, text='Delete task', width=42, command=delete_task)
button_delete_task.pack()
button_save_tasks = tk.Button(root, text='Save tasks', width=42, command=save_tasks)
button_save_tasks.pack()
button_prioritize_tasks = tk.Button(root, text='Prioritize', width=42, command=prioritize_tasks)
button_prioritize_tasks.pack()
load_tasks()
root.mainloop()
Note that I have:
add_task()
function inside new_task()
function in order to not using global variablesimpact()
function to assign a random impact value to the new taskload_tasks()
Better suggestion is to use ttk.Treeview()
instead of tk.Listbox()
because you can associate the impact value to the task using tags
or text
option of each record in the Treeview
.