我为待办事项列表中的项目制作的删除按钮只删除最后一个项目,而不删除其分配的项目

2024-10-01 09:37:42 发布

您现在位置:Python中文网/ 问答频道 /正文

我的代码:

# -*- coding: utf-8 -*-
"""
Created on Sun Jan 22 14:47:36 2017

@author: Jose Chong
"""
import json
import tkinter

master = tkinter.Tk()
master.title("To-Do List (with saving!)")
master.geometry("300x300")

masterFrame = tkinter.Frame(master)

masterFrame.pack(fill=tkinter.X)

checkboxArea = tkinter.Frame(masterFrame, height=26)

checkboxArea.pack(fill=tkinter.X)

inputStuff = tkinter.Frame(masterFrame)

checkboxList = []

with open('toDoListSaveFile.json') as infile:    
    checkboxList = json.load(infile)

for savedCheckbox in checkboxList:
    n = savedCheckbox
    def destroyCheckbox():
        checkboxRow.destroy()
        del checkboxList[checkboxList.index(str(savedCheckbox))]
    checkboxRow = tkinter.Frame(checkboxArea)
    checkboxRow.pack(fill=tkinter.X)
    checkbox1 = tkinter.Checkbutton(checkboxRow, text = n)
    checkbox1.pack(side=tkinter.LEFT)
    deleteItem = tkinter.Button(checkboxRow, text = "x", command=destroyCheckbox, bg="red", fg="white", activebackground="white", activeforeground="red")
    deleteItem.pack(side=tkinter.RIGHT)

def drawCheckbox():
    newCheckboxInput = entry.get()
    def destroyCheckbox():
        checkboxRow.destroy()
        del checkboxList[checkboxList.index(newCheckboxInput)]
    checkboxList.append(newCheckboxInput)
    entry.delete(0,tkinter.END)
    checkboxRow = tkinter.Frame(checkboxArea)
    checkboxRow.pack(fill=tkinter.X)
    checkbox1 = tkinter.Checkbutton(checkboxRow, text = checkboxList[-1])
    checkbox1.pack(side=tkinter.LEFT)
    deleteItem = tkinter.Button(checkboxRow, text = "x", command=destroyCheckbox, bg="red", fg="white", activebackground="white", activeforeground="red")
    deleteItem.pack(side=tkinter.RIGHT)

def createInputStuff():
    paddingFrame = tkinter.Frame(inputStuff, height=5)
    paddingFrame.pack(fill=tkinter.X)
    buttonDone.pack()
    inputStuff.pack()
    buttonAdd.pack_forget()
    master.bind('<Return>', lambda event: drawCheckbox())

def removeInputStuff():
    inputStuff.pack_forget()
    buttonAdd.pack()
    buttonDone.pack_forget()
    master.unbind('<Return>')


buttonDone = tkinter.Button(inputStuff, text = "Close Input", command=removeInputStuff)


buttonAdd = tkinter.Button(masterFrame, text="Add Item", command=createInputStuff)
buttonAdd.pack()


topInput = tkinter.Frame(inputStuff)
bottomInput = tkinter.Frame(inputStuff)

topInput.pack()
bottomInput.pack()

prompt = tkinter.Label(topInput, text="What do you want your checkbox to be for?")
prompt.pack()
entry = tkinter.Entry(bottomInput, bd=3)
entry.pack(side=tkinter.LEFT)
buttonConfirm = tkinter.Button(bottomInput, text="Confirm", command=drawCheckbox)
buttonConfirm.pack(side=tkinter.LEFT)

master.mainloop()

with open("toDoListSaveFile.json", 'w') as outfile:
    json.dump(checkboxList, outfile)

我的代码的相关位是for savedCheckbox in checkboxList:位(我认为),所以最好通读一下,这可能就是问题所在。你知道吗

这个问题与save文件中加载的复选框有关,或者更确切地说是它们的delete按钮。新的复选框中有delete按钮可以正常工作,但是使用for savedCheckbox in checkboxList:从save文件加载的复选框中有delete按钮不能正常工作。我的意思是:

它们都会删除最后加载的项(从保存文件中)。因此,如果我的保存文件是四个复选框[“f”,“a”,“c”,“e”]的列表,则每个加载的删除按钮都会删除“e”。如果你点击“c”旁边的删除按钮,太糟糕了,你正在删除“e”。如果我试图在“e”消失后删除任何内容,它会给出错误“ValueError:'e'不在列表中”。如果上次加载的复选框已经被删除,他们也不会销毁checkboxRow,我不确定这是复选框没有被删除的副作用,还是我把它也弄糟了。你知道吗

如何使“删除”按钮正常工作并正确删除复选框?适当的删除是:

从JSON文件中删除Checkbox的数据

复选框所在的整个复选框行也应删除,选中复选框、复选框旁边的文本,并使用“删除”按钮。你知道吗

关于“适当的”删除看起来像什么,请看drawCheckbox(),这就是创建工作删除框的地方。你知道吗


Tags: textmasterjsontkinterfill按钮frameside
1条回答
网友
1楼 · 发布于 2024-10-01 09:37:42

这是for循环中定义的函数的常见问题。你知道吗

def destroyCheckbox():
        checkboxRow.destroy()
        del checkboxList[checkboxList.index(str(savedCheckbox))]

destroyCheckbox销毁checkboxRow并从列表中删除savedCheckbox,但在for循环的末尾,checkboxRow是最后一行,savedCheckbox是最后一个复选框,因此所有按钮命令都执行相同的操作:删除最后一项。你知道吗

为了解决这个问题,我在for循环外用两个参数定义了函数destroyCheckbox:savedCheckbox和row。然后使用lambda和默认参数将命令传递给for循环中的按钮(请参见How to understand closure in a lambda?)。你知道吗

def destroyCheckbox(checkbox, row):
    row.destroy()
    checkboxList.remove(str(checkbox))

for savedCheckbox in checkboxList:
    checkboxRow = tkinter.Frame(checkboxArea)
    checkboxRow.pack(fill=tkinter.X)
    checkbox1 = tkinter.Checkbutton(checkboxRow, text=savedCheckbox)
    checkbox1.pack(side=tkinter.LEFT)
    deleteItem = tkinter.Button(checkboxRow, text="x", bg="red", fg="white",
                                activebackground="white", activeforeground="red",
                                command=lambda c=savedCheckbox, r=checkboxRow: destroyCheckbox(c, r))
    deleteItem.pack(side=tkinter.RIGHT)

相关问题 更多 >