0

I am a rookie making a to-do list-GUI in Tkinter. Every task in the to-do list has a class attribute associated with it. So a task is an object of Task: and it has a value attribute self.value. I want to sort all the tasks displayed in the GUI based on the attribute self.value. So for instance the task with the highest value is displayed on top of the list and the task with the lowest value is displayed at the bottom of the list. Note that it is not the value that must be displayed in the gui but the attribute self.name but it has to be displayed in an order based on the self.value.

I only understand conceptually what to do (i think). Somethng like, i need to make a list based on the self.value, then sort the "items" in the list from highest to lowest value, and then display the task.namein the gui based on the ordering of self.value.

Maybe I am retarded?

What would be the norm to do here?

EDIT

Code:

from tkinter import Tk, Frame, Button, Entry, Label, Toplevel
import tkinter.messagebox # Import the messagebox module

task_list = []
#value_list = [] 

class Task:
    def __init__(self, n, h):
        self.name = n
        self.hours = h

def show_tasks():
    task = task_list[-1]
    print('\n')
    print('_______________________')
    print('\n')
    print('Task:')
    print(task.name)
    print('\n')
    print('Hours')
    print(task.hours)

def open_add_task():
    taskwin = Toplevel(root)
    taskwin.focus_force()
    
    #NAME
    titlelabel = Label(taskwin, text='Title task concisely:', font=('Roboto',11,'bold')).grid(column=1, row=0)
    name_entry = Entry(taskwin, width=40, justify='center')
    name_entry.grid(column=1, row=1)

    #HOURS
    hourlabel = Label(taskwin, text='Whole hours \n required', font=('Roboto',10)).grid(column=1, row=2)
    hour_entry = Entry(taskwin, width=4, justify='center')
    hour_entry.grid(column=1, row=3)
    

    def add_task():
        if name_entry.get() != '':                 
            task_list.append(Task(name_entry.get(), hour_entry.get()))
            show_tasks()
            listbox_tasks.insert(tkinter.END, name_entry.get())
            name_entry.delete(0, tkinter.END)
            taskwin.destroy()
        else:
            tkinter.messagebox.showwarning(title='Whoops', message='You must enter a task')
      
    Add_button = Button(taskwin, text='Add', font=('Roboto',10), command=add_task).grid(column=1, row=4)
    
def sort_tasks():
    pass
    

root = Tk()

task_frame = Frame()
# Create UI
your_tasks_label = Label(root, text='THESE ARE YOUR TASKS:', font=('Roboto',10, 'bold'), justify='center')
your_tasks_label.pack()


listbox_tasks = tkinter.Listbox(root, height=10, width=50, font=('Roboto',10), justify='center') # tkinter.Listbox(where it should go, height=x, width=xx)
listbox_tasks.pack()


#BUTTONS
New_Task_Button = Button(root, text='New Task', width=42, command=open_add_task)
New_Task_Button.pack()


root.mainloop()
Karim Loberg
  • 95
  • 1
  • 7
  • Could you provide a [mre] of your try? I could interpret your requierments false since english isnt my native language. In addition, there could be planty of ways to achive this. A [mre] shows us where you at and what is needed to fill the lack of knowlege, so you benefit in the long run. – Thingamabobs May 29 '21 at 11:22
  • Thanks, I have added a piece of the code from my program – Karim Loberg May 29 '21 at 11:44

1 Answers1

2

There are multiple ways to do what you are trying to achieve.

The simplest way of all is to use the list.sort method and set reverse=True, which will sort in descending order. Assuming all your list values will be Task instances, In your case, you could do

todo_list.sort(key=lambda a: a.value, reverse=True)

Assuming your value attributes are integers. I made a small example.

names_values={"name1": 5, "name2": 10, "name3": 2}

todo_list = []

class Task:

    def __init__(self, name: str, value: int):
        self.name = name
        self.value = value

for key, value in names_values.items():
    task = Task(key, value)
    todo_list.append(task)

print("Before sorting: ", todo_list)
print("\nBefore sorting values: ", [(x.name, x.value) for x in todo_list])

todo_list.sort(key=lambda a: a.value, reverse=True)

print("\nAfter sorting: ", todo_list)
print("\nAfter sorting values: ", [(x.name, x.value) for x in todo_list])

Now you have a sorted list. You can now, iterate through list and use object.name to insert it to your list view.


updating since you added MRE:

Since you also need to show the sorted list in the GUI. you need to reload your list view. One way would to clear your list view and insert it again is as shown below.

...

    def add_task():
        if name_entry.get() != '':                 
            task_list.append(Task(name_entry.get(), int(hour_entry.get())))
            show_tasks()
            reload()
            taskwin.destroy()
        else:
            tkinter.messagebox.showwarning(title='Whoops', message='You must enter a task')
      
    Add_button = Button(taskwin, text='Add', font=('Roboto',10), command=add_task).grid(column=1, row=4)

def reload():
    task_list.sort(key=lambda a: a.hours, reverse=True)
    listbox_tasks.delete(0, tkinter.END)
    
    for x in task_list:
        listbox_tasks.insert(tkinter.END, x.name)
...
Art
  • 2,836
  • 4
  • 17
  • 34
  • Wow, this was really cool. I am a little confused about the ```task_list.sort(key=lambda a: a.hours, reverse=True)``` namely the ```(key=lambda a: a.hours``` part? Thanks for your effort! Also, I have made a "load" button which loads a list from a .dat file and a "Sort" button which calls ```reload()```. But if i load a list and then call ```reload()``` all tasks in the gui dissapear but I don't understand why. – Karim Loberg May 29 '21 at 12:51
  • @KarimLoberg [Check this](https://www.programiz.com/python-programming/methods/list/sort) you will have a clear understanding on how this works. In short, you can pass a specific function reference to the key parameter and it will sort based on what the function returns. In my case, I have used the [lambda](https://stackoverflow.com/a/890188/15993687) function for the same. The reason why everything disappears might be because your loaded list is empty. You might want to try printing the list before reloading. – Art May 29 '21 at 13:05
  • @KarimLoberg can you mark this answer as accepted if you found this helpful. – Art May 30 '21 at 13:46