Python,tkinter:无法使用 Pickle 保存
Python, tkinter: Can't save with Pickle
我不明白为什么我的代码不会 save/load 任何东西。
我希望用户能够在 GUI 中输入一个或多个任务,然后保存它们以便以后能够加载它们。我之前在另一个 GUI 中成功地完成了此操作,并且为此使用了相同的方法,但是它不起作用。
如果我按下加载它不会加载任何东西,而且保存过程中发生了什么我有点不清楚。
如果我 运行 程序,添加一个任务,保存它,然后删除它并按“加载任务”,它会显示类似 的内容<main.列表框中 0x0000018971142F10 处的任务对象>:
如果我创建了一个任务,保存它,关闭程序,然后再次 运行 然后按“加载任务”没有任何反应。
代码:
import tkinter.messagebox
import pickle
task_list = []
class Task:
def __init__(self, n):
self.name = n
def show_tasks():
task = task_list[-1]
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)
def add_task():
if name_entry.get() != '':
task_list.append(Task(name_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=2)
def delete_task():
try:
task_index = listbox_tasks.curselection()[0]
listbox_tasks.delete(task_index)
except:
tkinter.messagebox.showwarning(title='Error', message='You must select a task to delete')
def save_tasks():
tasks = listbox_tasks.get(0, listbox_tasks.size())
pickle.dump(tasks, open('Todo.dat', 'wb'))
def load_tasks():
try:
tasks = pickle.load(open('Todo.dat', 'rb'))
listbox_tasks.delete(0, tkinter.END)
for task in task_list:
listbox_tasks.insert(tkinter.END, task)
except:
tkinter.messagebox.showwarning(title='Error', message='You have no tasks')
root = Tk()
task_frame = Frame()
# 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')
listbox_tasks.pack()
#BUTTONS
New_Task_Button = Button(root, text='New Task', width=42, command=open_add_task)
New_Task_Button.pack()
button_delete_task = Button(root, text='Delete task', width=42, command=delete_task)
button_delete_task.pack()
button_save_tasks = Button(root, text='Save tasks', width=42, command=save_tasks)
button_save_tasks.pack()
button_load_tasks = Button(root, text='Load tasks', width=42, command=load_tasks)
button_load_tasks.pack()
root.mainloop()
正如我在评论中提到的,问题是您试图从包含 Task
class 对象的列表中读取。要访问任务的内容,您必须使用 object.name
.
由于您使用 tasks
变量存储 pickle 文件的内容,因此您需要在 for
循环中使用相同的内容。
我还想通知您,当您从 pickle 文件加载时,在关闭应用程序后,您不会将其插入 task_list
。
我建议您创建一个单独的函数,仅用于将任务插入 ListBox 并将其保存为一个列表,并在您从 pickle 文件加载时调用该函数。
...
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)
def add_task():
if name_entry.get() != '':
insertToList(name_entry.get())
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=2)
def insertToList(task):
task_list.append(Task(task))
show_tasks()
listbox_tasks.insert(tkinter.END, task)
def load_tasks():
global task_list
try:
with open('Todo.dat', 'rb') as f:
tasks = pickle.load(f)
listbox_tasks.delete(0, tkinter.END)
task_list = []
for task in tasks:
insertToList(task)
print(task_list, tasks)
except:
tkinter.messagebox.showwarning(title='Error', message='You have no tasks')
...
我不明白为什么我的代码不会 save/load 任何东西。
我希望用户能够在 GUI 中输入一个或多个任务,然后保存它们以便以后能够加载它们。我之前在另一个 GUI 中成功地完成了此操作,并且为此使用了相同的方法,但是它不起作用。 如果我按下加载它不会加载任何东西,而且保存过程中发生了什么我有点不清楚。
如果我 运行 程序,添加一个任务,保存它,然后删除它并按“加载任务”,它会显示类似 的内容<main.列表框中 0x0000018971142F10 处的任务对象>:
如果我创建了一个任务,保存它,关闭程序,然后再次 运行 然后按“加载任务”没有任何反应。
代码:
import tkinter.messagebox
import pickle
task_list = []
class Task:
def __init__(self, n):
self.name = n
def show_tasks():
task = task_list[-1]
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)
def add_task():
if name_entry.get() != '':
task_list.append(Task(name_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=2)
def delete_task():
try:
task_index = listbox_tasks.curselection()[0]
listbox_tasks.delete(task_index)
except:
tkinter.messagebox.showwarning(title='Error', message='You must select a task to delete')
def save_tasks():
tasks = listbox_tasks.get(0, listbox_tasks.size())
pickle.dump(tasks, open('Todo.dat', 'wb'))
def load_tasks():
try:
tasks = pickle.load(open('Todo.dat', 'rb'))
listbox_tasks.delete(0, tkinter.END)
for task in task_list:
listbox_tasks.insert(tkinter.END, task)
except:
tkinter.messagebox.showwarning(title='Error', message='You have no tasks')
root = Tk()
task_frame = Frame()
# 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')
listbox_tasks.pack()
#BUTTONS
New_Task_Button = Button(root, text='New Task', width=42, command=open_add_task)
New_Task_Button.pack()
button_delete_task = Button(root, text='Delete task', width=42, command=delete_task)
button_delete_task.pack()
button_save_tasks = Button(root, text='Save tasks', width=42, command=save_tasks)
button_save_tasks.pack()
button_load_tasks = Button(root, text='Load tasks', width=42, command=load_tasks)
button_load_tasks.pack()
root.mainloop()
正如我在评论中提到的,问题是您试图从包含 Task
class 对象的列表中读取。要访问任务的内容,您必须使用 object.name
.
由于您使用 tasks
变量存储 pickle 文件的内容,因此您需要在 for
循环中使用相同的内容。
我还想通知您,当您从 pickle 文件加载时,在关闭应用程序后,您不会将其插入 task_list
。
我建议您创建一个单独的函数,仅用于将任务插入 ListBox 并将其保存为一个列表,并在您从 pickle 文件加载时调用该函数。
...
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)
def add_task():
if name_entry.get() != '':
insertToList(name_entry.get())
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=2)
def insertToList(task):
task_list.append(Task(task))
show_tasks()
listbox_tasks.insert(tkinter.END, task)
def load_tasks():
global task_list
try:
with open('Todo.dat', 'rb') as f:
tasks = pickle.load(f)
listbox_tasks.delete(0, tkinter.END)
task_list = []
for task in tasks:
insertToList(task)
print(task_list, tasks)
except:
tkinter.messagebox.showwarning(title='Error', message='You have no tasks')
...