2016-08-12 52 views
-1

我正在開發一個Tkinter,Python 2.7的應用程序。 在我的一個進程中,我用26個小部件構建了窗口的一部分(根): 23個標籤,2個按鈕和1個條目。 在構建它們時,我不斷將其名稱添加到列表中,以便在完成使用後進一步銷燬 。爲此,我使用按鈕(「完成」) 中的一個按鈕來讀取創建的列表並在「for」循環內銷燬()它們。 小部件被不正常地破壞,不在列表中的順序。我需要按幾下按鈕才能完成它。 我發現出於沮喪,而不是洞察力,如果列表逆轉()在 「for」循環,他們都在第一次嘗試中被「銷燬」。 這是預期的行爲?非常迷惑! 我準備發佈我的應用程序的部分與奇怪的行爲 exponged不必要的代碼,除非有人已經知道它的原因。 我仍然在用Python截斷我的排序,但沒有準備好使用類... 謝謝!Tkinter對destroy的奇怪行爲()

我包括我的程序的相關部分。我編輯了原稿以減小尺寸。測試編輯後的版本,它具有相同的行爲。我評論了一些我的代碼,以顯示更正的位置。 奧克利先生很感興趣。我不確定是否在轉錄我的代碼時正確的縮進不受影響。

我的代碼:

# testdestroy.py 
from Tkinter import * 
root = Tk() 
root.title('Information container') 
root.geometry('1160x900+650+50') 

global todestroy, screen, font1, lbl1txt, lbl2txt 
global col, row, colincr, rowincr, bxincr, entries 

todestroy = [] 
screen = '' 
col = 10 
row = 10 
font1 = 'verdana 12 bold ' 
colincr = 370 
rowincr = 40 
bxincr = 145 

entries = {' Last updated: ' : '11/08/2016 at 11:55', 
      ' Login id: ' : 'calfucura', 
      ' Password: ': 'munafuca', 
      'card number' : '1234567890', 
      'check number': '445', 
      'expiry' : '12/06/2018', 
      'PIN' : '9890', 
      'Tel:' : '1-800-234-5678', 
      'emergency' : 'entry nine', 
      'use for' : 'gas, groceries'} 

def position(col, row, what):  # returns the position for the place command 
    colincr = 370 
    rowincr = 40 
    bxincr = 145 
    if what == 'down': 
     row += rowincr 
     col -= colincr 
    if what == 'side': 
     col += colincr 
    if what == 'button1': 
     row += rowincr 
     col += colincr - bxincr 
    if what == 'button': 
     col -= bxincr 
    if what == 'reset': 
     col = col 
     row = row 
    return col, row 

def done(event):      # Button "Done" 
    print 'Done pressed' 
    for name in todestroy:  # DOES NOT WORK!!!! 
           # THIS WORKS in the previous line: 
           # for name in reversed(todestroy): 
     name.destroy() 
     todestroy.remove(name) 

def accept(event):      # Button "Accept" 
    print 'Name to show: ', entry1.get() 
    scr2d1(entries) 

def scr2d():       # Name to show 
    lbl1txt = 'Enter name to show: ' 
    screen = 'scr2d' 
    scr2(lbl1txt) 
# scr2d1(entries) 

def scr2(lbl1txt): 
    global todestroy, col, row, entry1 
    lbl1 = Label(root, text = lbl1txt, anchor = E, width = 25, font = font1) 
    entry1 = Entry(root, width = 25, show = '*', font = font1) 
    Accept = Button(root, text = 'Accept', font = font1, bg = 'green', width = 9) 
    cmd = eval('Accept'.lower()) 
    Accept.bind('<ButtonRelease-1>', cmd) 
    col, row = position(200, 200, 'reset') 
    lbl1.place(x = col, y = row) 
    col, row = position(col, row, 'side') 
    entry1.place(x = col , y = row) 
    col, row = position(col, row, 'button1') 
    Accept.place(x = col, y = row) 
    todestroy = [] 
    todestroy.extend([lbl1, entry1, Accept]) 

def scr2d1(entries):    # show entries 
    global todestroy, col, row 
    lblup = 1 
    lbl = 'lbl' + str(lblup) 
    lbl = Label(root, text = 'Entry', font = font1, width = 20) 
    row = rowincr * 7 
    col = 600 
    col, row = position(col, row, 'down') 
    lbl.place(x = col, y = row) 
    todestroy.append(lbl) 
    lblup += 1 
    lbl = 'lbl' + str(lblup) 
    lbl = Label(root, text = 'Contents', font = font1, width = 20) 
    col, row = position(col, row, 'side') 
    lbl.place (x = col, y = row) 
    todestroy.append(lbl) 
    for name in sorted(entries): 
     lblup += 1 
     lbl = 'lbl' + str(lblup) 
     lbl = Label(root, text = name, bg = 'yellow', font = font1, width = 25, anchor = E) 
     col, row = position(col, row, 'down') 
     lbl.place(x = col, y = row) 
     todestroy.append(lbl) 
     lblup += 1 
     lbl = 'lbl' + str(lblup) 
     lbl = Label(root, text = entries[name], bg = 'yellow', font = font1, width = 25, anchor = W) 
     col, row = position(col, row, 'side') 
     lbl.place(x = col , y = row) 
     todestroy.append(lbl) 
    cmd = eval('done') 
    Done = Button(root, text = 'Done', font = font1, bg = 'green', width = 9) 
    Done.bind('<ButtonRelease-1>', cmd) 
    col, row = position(col, row, 'button1') 
    Done.place(x = col, y = row) 
    todestroy.append(Done) 

scr2d() 

root.mainloop()  
+0

請閱讀http://www.stackoverflow.com/help/mcve。不要發佈「你的應用程序的一部分」。相反,將其縮減爲一個能夠說明問題的小型工作程序。 –

+0

你是否知道刪除一個小部件將會摧毀它,並且它的所有孩子?您不需要逐個銷燬每個小部件。 –

+0

@BryanOakley我設計了一個單一的根窗口,沒有框架我的程序。我爲我所做的一切保留了根窗口。要使用我的代碼,請在「要顯示的名稱」中輸入任何字符,然後按「接受」。可能我正在提交「代碼sepuku」,但是......我從Tkinter開始,發現幀還不可管理。謝謝! – Albert

回答

1

的問題是,你遍歷它,這是不是你應該做的,你是改變列表。它與reversed一起使用的原因是因爲您正在迭代原始列表的副本。如果您使用for name in todestroy[:],您也會得到相同的結果,該結果也會迭代列表的副本。

最快的解決辦法是不從列表中刪除任何東西,只需重置該列表中,您已經刪除後一切:

def done(event): 
    global todestroy 
    for name in todestroy: 
     name.destroy() 
    todestroy = [] 

一個更好的解決辦法是把所有你打算摧毀小部件成Frame。然後你可以銷燬這個框架,並且它會銷燬它的所有子部件。

+0

@BrianOakley我很高興你花時間回覆。關於我的名單的好點!當我開始研究它時,我嘗試使用Frame,但在放置項目時遇到問題,因爲它看起來只有在您將小部件放在其上時纔會增長,並且在調試時很難看到結果。當我對自己正在做的事情更加自信時,我會再給Frames一個。這是我在Tkinter的第一次嘗試。非常感謝,我不喜歡「奧祕」... – Albert