2016-08-16 70 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