Tkinter无意识的递归与菜单栏命令...原因?

时间:2016-08-16 21:09:28

标签: python recursion tkinter

我正在尝试使用tkinter制作Python GUI,我需要一个菜单​​项来打开主窗口的另一个副本。我试着做下面的代码,当我运行程序时,它冻结了一点,然后打开了大量的窗口。打印的最后一条错误消息如下。

我有两个问题。

  1. 我怎样才能完成制作" New"按钮打开一个新窗口和TheThing类的实例? (在IDLE中,File > New File有我正在寻找的行为。)
  2. 为什么会发生这种错误?

    RecursionError: maximum recursion depth exceeded while calling a Python object
    
  3. 我的代码:

    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是关于recursion,python和tkinter的,但似乎更多的是after

1 个答案:

答案 0 :(得分: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))

此外,您可能只需在回调中创建一个Toplevel实例,而不是创建另一个Tk实例,即

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