【问题标题】:Python: Sorting based on class attributePython:基于类属性排序
【发布时间】:2021-08-17 09:36:43
【问题描述】:

我是一个新手,在 Tkinter 中制作待办事项列表-GUI。待办事项列表中的每个任务都有一个与之关联的类属性。 所以一个任务是Task:的一个对象,它有一个值属性self.value。 我想根据属性self.value 对GUI 中显示的所有任务进行排序。因此,例如具有最高值的任务显示在列表顶部,而具有最低值的任务显示在列表底部。 请注意,不是必须在 gui 中显示的值,而是属性 self.name,但它必须以 基于self.value 的顺序显示。

我只从概念上理解要做什么(我认为)。例如,我需要根据self.value 制作一个列表,然后将列表中的“项目”从最高值到最低值排序,然后根据self.value 的顺序在gui 中显示task.name

也许我是智障?

这里的规范是什么?

编辑

代码:

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()

【问题讨论】:

  • 你能提供一个minimal reproducible example你的尝试吗?由于英语不是我的母语,我可以将您的要求解释为错误的。此外,可能有很多方法可以实现这一目标。 minimal reproducible example 向我们展示了您在哪里以及需要什么来弥补知识的不足,因此您从长远来看会受益。
  • 谢谢,我从我的程序中添加了一段代码

标签: python-3.x list class sorting tkinter


【解决方案1】:

有多种方法可以实现您想要实现的目标。

最简单的方法是使用list.sort 方法并设置reverse=True,它将按降序排序。假设您的所有列表值都是 Task 实例,在您的情况下,您可以这样做

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

假设您的值属性是整数。我做了一个小例子。

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])

现在您有了一个排序列表。您现在可以遍历列表并使用object.name 将其插入到您的列表视图中。


自您添加 MRE 后更新:

因为您还需要在 GUI 中显示排序列表。您需要重新加载列表视图。一种清除列表视图并再次插入的方法如下所示。

...

    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)
...

【讨论】:

  • 哇,这真的很酷。我对task_list.sort(key=lambda a: a.hours, reverse=True)(key=lambda a: a.hours 部分有点困惑?谢谢你的努力!此外,我还制作了一个“加载”按钮,该按钮从 .dat 文件加载列表,以及一个调用 reload() 的“排序”按钮。但是如果我加载一个列表然后调用reload() gui 中的所有任务消失,但我不明白为什么。
  • @KarimLoberg Check this 您将清楚地了解其工作原理。简而言之,您可以将特定的函数引用传递给 key 参数,它将根据函数返回的内容进行排序。就我而言,我也使用了lambda 函数。一切都消失的原因可能是因为您加载的列表是空的。您可能想在重新加载之前尝试打印列表。
  • @KarimLoberg 如果您觉得此答案有帮助,您能否将此答案标记为已接受。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-16
  • 1970-01-01
  • 2014-07-09
  • 1970-01-01
  • 1970-01-01
  • 2011-06-02
  • 2014-03-06
相关资源
最近更新 更多