2016-08-16 71 views
2

我想使用tkinter製作一個Python GUI,我需要一個菜單​​項打開主窗口的另一個副本。我試着做下面的代碼,當我運行程序時,它凍結了一下,然後打開了大量的窗口。最後打印的錯誤信息如下。Tkinter無意中遞歸與菜單欄命令...原因?

我有兩個問題。

  1. 我該如何完成使「新建」按鈕打開一個新窗口和TheThing類的實例的任務? (在IDLE中,File > New File具有我正在尋找的行爲。)
  2. 爲什麼會發生此錯誤?

    RecursionError: maximum recursion depth exceeded while calling a Python object 
    

我的代碼:

import tkinter as tk 

class TheThing: 
    def __init__(self, root): 
     root.option_add('*tearOff', False) 

     menubar = tk.Menu(root) 
     root.config(menu = menubar) 

     file = tk.Menu(menubar) 
     menubar.add_cascade(menu = file, label = "File") 
     file.add_command(label = 'New', command = doathing()) 

def doathing(): 
    thing1 = tk.Tk() 
    thing2 = TheThing(thing1) 

def main(): 
    win = tk.Tk() 
    do = TheThing(win) 
    win.mainloop() 

if __name__ == '__main__': main() 

地方我已經找了答案:

  • This question好像它是具有非常類似的問題。我可能可以研究並找到解決方案,但我仍然不會理解問題。

  • This question是關於遞歸,python和tkinter,但似乎更多的是after的事情。

+0

'command = d oathing()'立即執行回調(並且在回調中創建一個新的窗口,進行無限遞歸),並將其結果綁定到'command'參數。刪除'()'。而且,那究竟是幹什麼呢? –

+0

修復了它。我刪除了'()',它看起來像預期的那樣工作。它應該打開一個新窗口,完全像舊窗口。 Python IDLE文本編輯器在'File> New File'下有這種行爲。謝謝。 – rod

回答

2

的問題是在這條線:

file.add_command(label = 'New', command = doathing()) 

在這裏,你執行doathing回調,然後嘗試它的結果結合(這是None)的命令。在這種特定情況下,這也會導致無限遞歸,因爲回調將創建一個新的框架實例,它將再次執行回調,這將創建另一個框架,依此類推。您不必調用該函數,而必須將函數本身綁定到該命令。

file.add_command(label = 'New', command = doathing) # no() 

如果您需要將參數傳遞給函數(不是這裏的情況),您可以使用一個lambda

file.add_command(label = 'New', command = lambda: doathing(params)) 

此外,而不是創建另一個Tk情況下,你或許應該只需在回調中創建一個Toplevel實例,即

def doathing(): 
    thing1 = tk.Toplevel() 
    thing2 = TheThing(thing1) 
+0

謝謝。你的回答非常有幫助。你不僅回答了我問過的問題,而且你回答了很多關於我在閱讀你的答案時想知道的問題。 – rod