2017-01-26 65 views
1

我的代码:删除按钮,我的项目在待办事项列表仅取得删除的最后一个项目,而不是分配给他们的项目

# -*- 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:位(我认为) ,所以在这里阅读是个好主意,这可能是问题所在。

问题是如何处理保存文件中已加载的复选框,或者更确切地说是删除按钮。新的复选框具有删除按钮,可以正常工作,但使用for savedCheckbox in checkboxList:从保存文件加载的删除按钮有故障。我的意思是:

他们都删除最后加载的项目(从保存文件)。因此,如果我的保存文件是四个复选框[“f”,“a”,“c”,“e”]的列表,则每个加载的删除按钮都会删除“e”。如果你点击“c”旁边的删除按钮,太糟糕了,你正在删除“e”。如果我在“e”消失后尝试删除任何东西,它会给我错误“ValueError:'e'不在列表中”。如果最后一个已加载的复选框已被删除,它们也不会破坏checkboxRow,我不确定这是复选框未被删除的副作用还是我也搞砸了。

如何让我的删除按钮正常工作并正确删除复选框?正确的删除是:

复选框的数据从JSON文件

整个checkboxRow的复选框去掉也应该被删除,同时旁边的复选框,文本的复选框,并与它删除按钮。

对于什么“正确的”删除看起来像看看drawCheckbox(),这是工作删除框的地方。

回答

0

这是循环内定义函数的常见问题。

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) 
+0

感谢您的解决方案,它的工作!我不明白的是,destroyCheckbox()知道“复选框”是指加载的复选框文本,而“行”是指checkboxRow。你能解释一下吗? –

+0

其实我认为你在lambda中指定了那些。谢谢您的帮助! –

+0

确切的说,当我将命令传递给按钮时,我将复选框和行分配给lambda中的正确对象。 –