2017-01-26 100 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中的正確對象。 –