我正在用Python制作一个简单的任务管理器,但我想不出一种方法可以让按钮删除任务(如果制作完成)。
我尝试制作一个删除项目的功能,但没有成功。由于某种原因,该函数仅删除第一项,然后开始给出错误:
ValueError:list.remove(x):x不在列表中
import json
from tkinter import *
PATH = "data.json"
class Data:
data: list[dict] = []
def __init__(self):
self.read_data()
def read_data(self):
with open(PATH, "r") as file:
self.data = json.load(file)
def write_data(self):
with open(PATH, "w") as file:
json.dump(self.data, file, indent=4)
def update_ids(self):
id = 0
for task in self.data:
task['id'] = id
id += 1
self.write_data()
def write_task(self, name: str, date: str, importance: str):
self.data.append({
"name": name,
"date": date,
"importance": importance,
"id": self.data[-1]['id'] + 1
})
self.write_data()
def get_task(self, id: int) -> dict:
for task in self.data:
if task['id'] == id:
return task
def __iter__(self):
for task in self.data:
yield task
def delete_task(self, id: int):
self.data = [task for task in self.data if task['id'] != id]
self.write_data()
Tasks = Data()
class Window(Tk):
tasks: list[dict] = []
def __init__(self):
super().__init__()
self.protocol("WM_DELETE_WINDOW", self.on_closing)
self.create_tasks()
self.render_tasks()
self.mainloop()
def create_tasks(self):
for task in Tasks:
label = Label(self, text=f"task :{task['name']} \ndate : {task['date']}", fg=task['importance'])
button = Button(self, text="Delete")
pack = {
"label": label,
"button": button
}
self.tasks.append(pack)
def function():
label.destroy()
button.destroy()
self.tasks.remove(pack)
Tasks.delete_task(task['id'])
self.render_tasks()
button.config(command=function)
def render_tasks(self):
for task in self.tasks:
task['label'].pack()
task['button'].pack()
def on_closing(self):
Tasks.update_ids()
self.destroy()
if __name__ == "__main__":
wnd = Window()
您遇到的问题是如何定义 function() 。您在其中所做的就是引用局部变量(标签、按钮、包……),这些变量在您执行循环时会被修改。循环完成后,这些变量保留最后一次迭代的值,这就是为什么您总是在第一次按时删除最后一个(无论按哪个按钮),而第二次则失败。
您可以做的是为所有这些值找到一些外部存储,以便您可以在删除时引用它们,并使用部分定义每个按钮的命令,以便每个按钮都有它所引用的条目的标识(如此处所解释)。
我对你的程序做了一个非常粗略的修改来展示这个想法。至少您会看到正确的项目从窗口中消失,尽管它缺少数据中的删除:
import json
from tkinter import *
from functools import partial
PATH = "data.json"
class Data:
data: list[dict] = []
def __init__(self):
self.read_data()
def read_data(self):
with open(PATH, "r") as file:
self.data = json.load(file)
def write_data(self):
with open(PATH, "w") as file:
json.dump(self.data, file, indent=4)
def update_ids(self):
id = 0
for task in self.data:
task['id'] = id
id += 1
self.write_data()
def write_task(self, name: str, date: str, importance: str):
self.data.append({
"name": name,
"date": date,
"importance": importance,
"id": self.data[-1]['id'] + 1
})
self.write_data()
def get_task(self, id: int) -> dict:
for task in self.data:
if task['id'] == id:
return task
def __iter__(self):
for task in self.data:
yield task
def delete_task(self, id: int):
self.data = [task for task in self.data if task['id'] != id]
self.write_data()
Tasks = Data()
class Window(Tk):
tasks: dict[dict] = {}
def __init__(self):
super().__init__()
self.protocol("WM_DELETE_WINDOW", self.on_closing)
self.create_tasks()
self.render_tasks()
self.mainloop()
def create_tasks(self):
for task in Tasks:
label_text = f"task :{task['name']} \ndate : {task['date']}"
label = Label(self, text=label_text, fg=task['importance'])
button = Button(self, text="Delete")
pack = {
"label": label,
"button": button
}
self.tasks[label_text]=pack
def function(t):
print(t)
print(self.tasks[t])
self.tasks[t]['label'].destroy()
self.tasks[t]['button'].destroy()
#Tasks.delete_task(self.tasks[t]['id'])
self.tasks.pop(t)
self.render_tasks()
button.config(command=partial(function, label_text))
def render_tasks(self):
for task in self.tasks.values():
print(task)
task['label'].pack()
task['button'].pack()
def on_closing(self):
Tasks.update_ids()
self.destroy()
if __name__ == "__main__":
wnd = Window()